summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2014-07-09 17:38:57 -0700
committerKenneth Graunke <kenneth@whitecape.org>2014-07-13 23:31:11 -0700
commit24e97e5ba02d49555cd02774186114e616750762 (patch)
tree07df12b5930845d53ac8cf4f48c5aa0544f051be
parenta45fe61c16a31ecefc50ceb4db451a3e0c6f5d81 (diff)
Update Warsow shaders to 1.5.0.
$ warsow +timedemo 1 +cg_showFPS 1 +cl_checkForUpdate 0 \ +demo pts1 +next "quit"
-rw-r--r--shaders/warsow/1.shader_test2244
-rw-r--r--shaders/warsow/10.shader_test1968
-rw-r--r--shaders/warsow/100.shader_test1673
-rw-r--r--shaders/warsow/103.shader_test2057
-rw-r--r--shaders/warsow/106.shader_test2059
-rw-r--r--shaders/warsow/109.shader_test1753
-rw-r--r--shaders/warsow/112.shader_test2061
-rw-r--r--shaders/warsow/115.shader_test2055
-rw-r--r--shaders/warsow/118.shader_test1675
-rw-r--r--shaders/warsow/121.shader_test2057
-rw-r--r--shaders/warsow/124.shader_test1239
-rw-r--r--shaders/warsow/127.shader_test2059
-rw-r--r--shaders/warsow/13.shader_test1508
-rw-r--r--shaders/warsow/130.shader_test2057
-rw-r--r--shaders/warsow/133.shader_test1419
-rw-r--r--shaders/warsow/136.shader_test2059
-rw-r--r--shaders/warsow/139.shader_test1675
-rw-r--r--shaders/warsow/142.shader_test1753
-rw-r--r--shaders/warsow/145.shader_test2063
-rw-r--r--shaders/warsow/148.shader_test2061
-rw-r--r--shaders/warsow/151.shader_test1753
-rw-r--r--shaders/warsow/154.shader_test1421
-rw-r--r--shaders/warsow/157.shader_test1431
-rw-r--r--shaders/warsow/16.shader_test1798
-rw-r--r--shaders/warsow/160.shader_test1431
-rw-r--r--shaders/warsow/163.shader_test2061
-rw-r--r--shaders/warsow/166.shader_test2061
-rw-r--r--shaders/warsow/169.shader_test1753
-rw-r--r--shaders/warsow/172.shader_test1753
-rw-r--r--shaders/warsow/175.shader_test1755
-rw-r--r--shaders/warsow/178.shader_test2059
-rw-r--r--shaders/warsow/181.shader_test2059
-rw-r--r--shaders/warsow/184.shader_test2057
-rw-r--r--shaders/warsow/187.shader_test1751
-rw-r--r--shaders/warsow/19.shader_test1440
-rw-r--r--shaders/warsow/190.shader_test2061
-rw-r--r--shaders/warsow/193.shader_test1753
-rw-r--r--shaders/warsow/196.shader_test1675
-rw-r--r--shaders/warsow/199.shader_test1241
-rw-r--r--shaders/warsow/202.shader_test1755
-rw-r--r--shaders/warsow/205.shader_test2084
-rw-r--r--shaders/warsow/208.shader_test1698
-rw-r--r--shaders/warsow/211.shader_test1793
-rw-r--r--shaders/warsow/214.shader_test1784
-rw-r--r--shaders/warsow/217.shader_test1782
-rw-r--r--shaders/warsow/22.shader_test1100
-rw-r--r--shaders/warsow/220.shader_test1784
-rw-r--r--shaders/warsow/223.shader_test1797
-rw-r--r--shaders/warsow/226.shader_test1784
-rw-r--r--shaders/warsow/229.shader_test1795
-rw-r--r--shaders/warsow/232.shader_test1784
-rw-r--r--shaders/warsow/235.shader_test2063
-rw-r--r--shaders/warsow/238.shader_test2059
-rw-r--r--shaders/warsow/241.shader_test1421
-rw-r--r--shaders/warsow/244.shader_test1421
-rw-r--r--shaders/warsow/247.shader_test1675
-rw-r--r--shaders/warsow/25.shader_test5279
-rw-r--r--shaders/warsow/250.shader_test1675
-rw-r--r--shaders/warsow/253.shader_test1698
-rw-r--r--shaders/warsow/256.shader_test1677
-rw-r--r--shaders/warsow/259.shader_test1675
-rw-r--r--shaders/warsow/262.shader_test1795
-rw-r--r--shaders/warsow/28.shader_test1031
-rw-r--r--shaders/warsow/30.shader_test26
-rw-r--r--shaders/warsow/31.shader_test2246
-rw-r--r--shaders/warsow/34.shader_test2256
-rw-r--r--shaders/warsow/37.shader_test2258
-rw-r--r--shaders/warsow/4.shader_test1528
-rw-r--r--shaders/warsow/40.shader_test1976
-rw-r--r--shaders/warsow/43.shader_test1972
-rw-r--r--shaders/warsow/46.shader_test1804
-rw-r--r--shaders/warsow/49.shader_test2084
-rw-r--r--shaders/warsow/52.shader_test2046
-rw-r--r--shaders/warsow/55.shader_test1273
-rw-r--r--shaders/warsow/58.shader_test1751
-rw-r--r--shaders/warsow/60.shader_test17
-rw-r--r--shaders/warsow/61.shader_test2057
-rw-r--r--shaders/warsow/63.shader_test22
-rw-r--r--shaders/warsow/64.shader_test1979
-rw-r--r--shaders/warsow/67.shader_test2256
-rw-r--r--shaders/warsow/7.shader_test1290
-rw-r--r--shaders/warsow/70.shader_test1514
-rw-r--r--shaders/warsow/73.shader_test2262
-rw-r--r--shaders/warsow/76.shader_test1518
-rw-r--r--shaders/warsow/79.shader_test2260
-rw-r--r--shaders/warsow/82.shader_test2110
-rw-r--r--shaders/warsow/85.shader_test2080
-rw-r--r--shaders/warsow/88.shader_test2048
-rw-r--r--shaders/warsow/91.shader_test2052
-rw-r--r--shaders/warsow/94.shader_test2059
-rw-r--r--shaders/warsow/97.shader_test2057
91 files changed, 155342 insertions, 8676 deletions
diff --git a/shaders/warsow/1.shader_test b/shaders/warsow/1.shader_test
index f005219..fc589b9 100644
--- a/shaders/warsow/1.shader_test
+++ b/shaders/warsow/1.shader_test
@@ -1,138 +1,766 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -140,342 +768,1022 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-gl_FragColor = vec4(color);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
}
-#endif // FRAGMENT_SHADER
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#endif
+#endif
-#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-uniform vec3 EyeOrigin;
+uniform Fog u_Fog;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -483,207 +1791,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
-#ifdef APPLY_LIGHTSTYLE0
+ // deluxemapping using light vectors in modelspace
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/10.shader_test b/shaders/warsow/10.shader_test
index de4bd35..93aaa73 100644
--- a/shaders/warsow/10.shader_test
+++ b/shaders/warsow/10.shader_test
@@ -1,695 +1,1669 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
-#endif
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
-// deluxemapping using light vectors in modelspace
+uniform myhalf2 u_BlendMix;
-#ifdef APPLY_LIGHTSTYLE0
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+uniform float u_MirrorSide;
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+uniform float u_ZNear, u_ZFar;
-#define NORMALIZE_DIFFUSE_NORMAL
+uniform ivec4 u_Viewport; // x, y, width, height
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+uniform vec4 u_TextureParams;
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
-#endif
-#endif
-#endif
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_SPECULAR
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
#else
-gl_FragColor = vec4(color);
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
}
#endif // FRAGMENT_SHADER
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
+[fragment shader]
+#version 130
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
-#endif
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
-// deluxemapping using light vectors in modelspace
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
-#ifdef APPLY_LIGHTSTYLE0
+uniform myhalf2 u_BlendMix;
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+uniform float u_MirrorSide;
-#define NORMALIZE_DIFFUSE_NORMAL
+uniform float u_ZNear, u_ZFar;
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+uniform ivec4 u_Viewport; // x, y, width, height
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
-#endif
-#endif
-#endif
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_SPECULAR
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
#else
-gl_FragColor = vec4(color);
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
}
#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/100.shader_test b/shaders/warsow/100.shader_test
new file mode 100644
index 0000000..ff9a2dc
--- /dev/null
+++ b/shaders/warsow/100.shader_test
@@ -0,0 +1,1673 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/103.shader_test b/shaders/warsow/103.shader_test
new file mode 100644
index 0000000..1f311c4
--- /dev/null
+++ b/shaders/warsow/103.shader_test
@@ -0,0 +1,2057 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/106.shader_test b/shaders/warsow/106.shader_test
new file mode 100644
index 0000000..f233b69
--- /dev/null
+++ b/shaders/warsow/106.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/109.shader_test b/shaders/warsow/109.shader_test
new file mode 100644
index 0000000..08ae3bb
--- /dev/null
+++ b/shaders/warsow/109.shader_test
@@ -0,0 +1,1753 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/112.shader_test b/shaders/warsow/112.shader_test
new file mode 100644
index 0000000..baa52fe
--- /dev/null
+++ b/shaders/warsow/112.shader_test
@@ -0,0 +1,2061 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/115.shader_test b/shaders/warsow/115.shader_test
new file mode 100644
index 0000000..9312ee6
--- /dev/null
+++ b/shaders/warsow/115.shader_test
@@ -0,0 +1,2055 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/118.shader_test b/shaders/warsow/118.shader_test
new file mode 100644
index 0000000..ac1d742
--- /dev/null
+++ b/shaders/warsow/118.shader_test
@@ -0,0 +1,1675 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/121.shader_test b/shaders/warsow/121.shader_test
new file mode 100644
index 0000000..db7e332
--- /dev/null
+++ b/shaders/warsow/121.shader_test
@@ -0,0 +1,2057 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_HALFLAMBERT
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_HALFLAMBERT
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/124.shader_test b/shaders/warsow/124.shader_test
new file mode 100644
index 0000000..3518fbc
--- /dev/null
+++ b/shaders/warsow/124.shader_test
@@ -0,0 +1,1239 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform float u_OutlineHeight;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
+#endif
+
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
+#endif
+ qf_FragColor = vec4(qf_FrontColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform float u_OutlineHeight;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
+#endif
+
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
+#endif
+ qf_FragColor = vec4(qf_FrontColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/127.shader_test b/shaders/warsow/127.shader_test
new file mode 100644
index 0000000..dd7da3c
--- /dev/null
+++ b/shaders/warsow/127.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/13.shader_test b/shaders/warsow/13.shader_test
index 4a2358e..de78c04 100644
--- a/shaders/warsow/13.shader_test
+++ b/shaders/warsow/13.shader_test
@@ -1,691 +1,1233 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_DIRECTIONAL_LIGHT
-#define APPLY_CELLSHADING
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE0
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_SPECULAR
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform float u_OutlineHeight;
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
#endif
+ qf_FragColor = vec4(qf_FrontColor);
}
#endif // FRAGMENT_SHADER
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_DIRECTIONAL_LIGHT
-#define APPLY_CELLSHADING
-// Warsow GLSL shader
+[fragment shader]
+#version 130
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE0
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_SPECULAR
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform float u_OutlineHeight;
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
#endif
+ qf_FragColor = vec4(qf_FrontColor);
}
#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/130.shader_test b/shaders/warsow/130.shader_test
new file mode 100644
index 0000000..be9ef9c
--- /dev/null
+++ b/shaders/warsow/130.shader_test
@@ -0,0 +1,2057 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/133.shader_test b/shaders/warsow/133.shader_test
new file mode 100644
index 0000000..0401722
--- /dev/null
+++ b/shaders/warsow/133.shader_test
@@ -0,0 +1,1419 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/136.shader_test b/shaders/warsow/136.shader_test
new file mode 100644
index 0000000..442e1f2
--- /dev/null
+++ b/shaders/warsow/136.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/139.shader_test b/shaders/warsow/139.shader_test
new file mode 100644
index 0000000..de3325b
--- /dev/null
+++ b/shaders/warsow/139.shader_test
@@ -0,0 +1,1675 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 3
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 3
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/142.shader_test b/shaders/warsow/142.shader_test
new file mode 100644
index 0000000..cd94720
--- /dev/null
+++ b/shaders/warsow/142.shader_test
@@ -0,0 +1,1753 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/145.shader_test b/shaders/warsow/145.shader_test
new file mode 100644
index 0000000..ddbb508
--- /dev/null
+++ b/shaders/warsow/145.shader_test
@@ -0,0 +1,2063 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DECAL
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DECAL
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/148.shader_test b/shaders/warsow/148.shader_test
new file mode 100644
index 0000000..25d520f
--- /dev/null
+++ b/shaders/warsow/148.shader_test
@@ -0,0 +1,2061 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/151.shader_test b/shaders/warsow/151.shader_test
new file mode 100644
index 0000000..da69ea7
--- /dev/null
+++ b/shaders/warsow/151.shader_test
@@ -0,0 +1,1753 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/154.shader_test b/shaders/warsow/154.shader_test
new file mode 100644
index 0000000..64b5ca9
--- /dev/null
+++ b/shaders/warsow/154.shader_test
@@ -0,0 +1,1421 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/157.shader_test b/shaders/warsow/157.shader_test
new file mode 100644
index 0000000..ff46693
--- /dev/null
+++ b/shaders/warsow/157.shader_test
@@ -0,0 +1,1431 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_ENTITY_DECAL
+#define APPLY_STRIPES
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT_ADD
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_ENTITY_DECAL
+#define APPLY_STRIPES
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT_ADD
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/16.shader_test b/shaders/warsow/16.shader_test
index 76c961a..ffa5bbe 100644
--- a/shaders/warsow/16.shader_test
+++ b/shaders/warsow/16.shader_test
@@ -1,307 +1,1747 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec4 TexCoord;
-varying vec4 ProjVector;
-#ifdef APPLY_EYEDOT
-varying vec3 EyeVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-#ifdef APPLY_EYEDOT
-uniform vec3 EyeOrigin;
-uniform float FrontPlane;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
-TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-textureMatrix = gl_TextureMatrix[0];
-textureMatrix[0] = -textureMatrix[0];
-textureMatrix[1] = -textureMatrix[1];
-TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_EYEDOT
-mat3 strMatrix;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_Position = ftransform();
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-#ifdef APPLY_DUDV
-uniform sampler2D DuDvMapTexture;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-#ifdef APPLY_EYEDOT
-uniform sampler2D NormalmapTexture;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-uniform sampler2D ReflectionTexture;
-uniform sampler2D RefractionTexture;
-uniform float TextureWidth, TextureHeight;
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-myhalf3 color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_DUDV
-vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));
-vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-vec3 fdist = vec3(0.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
-// get projective texcoords
-float scale = float(1.0 / float(ProjVector.w));
-float inv2NW = 1.0 / (2.0 * float (TextureWidth));
-float inv2NH = 1.0 / (2.0 * float (TextureHeight));
-vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
-projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
-projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+uniform float u_MirrorSide;
-myhalf3 refr = myhalf3(0.0);
-myhalf3 refl = myhalf3(0.0);
+uniform float u_ZNear, u_ZFar;
-#ifdef APPLY_EYEDOT
-// calculate dot product between the surface normal and eye vector
-// great for simulating varying water translucency based on the view angle
-myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5));
-vec3 eyeNormal = normalize(myhalf3(EyeVector));
+uniform ivec4 u_Viewport; // x, y, width, height
-float refrdot = float(dot(surfaceNormal, eyeNormal));
-//refrdot = float (clamp (refrdot, 0.0, 1.0));
-float refldot = 1.0 - refrdot;
-// get refraction and reflection
+uniform vec4 u_TextureParams;
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot;
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot;
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord)));
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord)));
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
#endif
#endif
+#endif
-// add reflection and refraction
-#ifdef APPLY_DISTORTION_ALPHA
-color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color = myhalf3(gl_Color.rgb) + refr + refl;
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),1.0);
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
#else
-gl_FragColor = vec4(vec3(color),1.0);
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
}
-#endif // FRAGMENT_SHADER
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
-#if !defined(__GLSL_CG_DATA_TYPES)
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying vec4 TexCoord;
-varying vec4 ProjVector;
-#ifdef APPLY_EYEDOT
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_EYEDOT
-uniform vec3 EyeOrigin;
-uniform float FrontPlane;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
-TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-textureMatrix = gl_TextureMatrix[0];
-textureMatrix[0] = -textureMatrix[0];
-textureMatrix[1] = -textureMatrix[1];
-TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_EYEDOT
-mat3 strMatrix;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_Position = ftransform();
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-#ifdef APPLY_DUDV
-uniform sampler2D DuDvMapTexture;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-#ifdef APPLY_EYEDOT
-uniform sampler2D NormalmapTexture;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-uniform sampler2D ReflectionTexture;
-uniform sampler2D RefractionTexture;
-uniform float TextureWidth, TextureHeight;
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
{
-myhalf3 color;
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
-#ifdef APPLY_DUDV
-vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));
-vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-vec3 fdist = vec3(0.0);
+qf_varying vec2 v_TexCoord;
#endif
-// get projective texcoords
-float scale = float(1.0 / float(ProjVector.w));
-float inv2NW = 1.0 / (2.0 * float (TextureWidth));
-float inv2NH = 1.0 / (2.0 * float (TextureHeight));
-vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
-projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
-projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
-myhalf3 refr = myhalf3(0.0);
-myhalf3 refl = myhalf3(0.0);
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-#ifdef APPLY_EYEDOT
-// calculate dot product between the surface normal and eye vector
-// great for simulating varying water translucency based on the view angle
-myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5));
-vec3 eyeNormal = normalize(myhalf3(EyeVector));
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-float refrdot = float(dot(surfaceNormal, eyeNormal));
-//refrdot = float (clamp (refrdot, 0.0, 1.0));
-float refldot = 1.0 - refrdot;
-// get refraction and reflection
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot;
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord)));
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord)));
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-// add reflection and refraction
-#ifdef APPLY_DISTORTION_ALPHA
-color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-color = myhalf3(gl_Color.rgb) + refr + refl;
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),1.0);
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-gl_FragColor = vec4(vec3(color),1.0);
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
}
-#endif // FRAGMENT_SHADER
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/160.shader_test b/shaders/warsow/160.shader_test
new file mode 100644
index 0000000..1afe69a
--- /dev/null
+++ b/shaders/warsow/160.shader_test
@@ -0,0 +1,1431 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_ENTITY_DECAL
+#define APPLY_STRIPES
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT_ADD
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_ENTITY_DECAL
+#define APPLY_STRIPES
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT
+#define APPLY_CEL_LIGHT_ADD
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/163.shader_test b/shaders/warsow/163.shader_test
new file mode 100644
index 0000000..dba7913
--- /dev/null
+++ b/shaders/warsow/163.shader_test
@@ -0,0 +1,2061 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/166.shader_test b/shaders/warsow/166.shader_test
new file mode 100644
index 0000000..8810c5c
--- /dev/null
+++ b/shaders/warsow/166.shader_test
@@ -0,0 +1,2061 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/169.shader_test b/shaders/warsow/169.shader_test
new file mode 100644
index 0000000..81d4852
--- /dev/null
+++ b/shaders/warsow/169.shader_test
@@ -0,0 +1,1753 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_TC_GEN_REFLECTION
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_TC_GEN_REFLECTION
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/172.shader_test b/shaders/warsow/172.shader_test
new file mode 100644
index 0000000..caf1298
--- /dev/null
+++ b/shaders/warsow/172.shader_test
@@ -0,0 +1,1753 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_TC_GEN_ENV
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_TC_GEN_ENV
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/175.shader_test b/shaders/warsow/175.shader_test
new file mode 100644
index 0000000..5194082
--- /dev/null
+++ b/shaders/warsow/175.shader_test
@@ -0,0 +1,1755 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_TC_GEN_ENV
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_TC_GEN_ENV
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/178.shader_test b/shaders/warsow/178.shader_test
new file mode 100644
index 0000000..723cd6a
--- /dev/null
+++ b/shaders/warsow/178.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/181.shader_test b/shaders/warsow/181.shader_test
new file mode 100644
index 0000000..d0ab50b
--- /dev/null
+++ b/shaders/warsow/181.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/184.shader_test b/shaders/warsow/184.shader_test
new file mode 100644
index 0000000..ef4c4a0
--- /dev/null
+++ b/shaders/warsow/184.shader_test
@@ -0,0 +1,2057 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/187.shader_test b/shaders/warsow/187.shader_test
new file mode 100644
index 0000000..480a43a
--- /dev/null
+++ b/shaders/warsow/187.shader_test
@@ -0,0 +1,1751 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_VERTEX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_VERTEX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/19.shader_test b/shaders/warsow/19.shader_test
index 9b644bc..26aac1d 100644
--- a/shaders/warsow/19.shader_test
+++ b/shaders/warsow/19.shader_test
@@ -1,225 +1,1415 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 ProjVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-void main(void)
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-mat4 textureMatrix;
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-gl_Position = ftransform();
-ProjVector = textureMatrix * gl_Vertex;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-uniform myhalf3 LightAmbient;
-uniform float TextureWidth, TextureHeight;
-uniform float ProjDistance;
-uniform sampler2DShadow ShadowmapTexture;
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
void main(void)
{
-myhalf color = myhalf(1.0);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
-if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance)
-discard;
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
-float dtW = 1.0 / TextureWidth;
-float dtH = 1.0 / TextureHeight;
+ qf_FrontColor = vec4(outColor);
-vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);
-coord = (coord + vec3 (1.0)) * vec3 (0.5);
-coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));
-coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));
-coord.r = float (clamp (float(coord.r), 0.0, 1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
-myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r);
-myhalf shadow = shadow0;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
-#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)
+#endif // VERTEX_SHADER
-vec3 coord2 = coord + vec3(0.0, dtH, 0.0);
-myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef FRAGMENT_SHADER
+// Fragment shader
-coord2 = coord + vec3(dtW, dtH, 0.0);
-myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
-coord2 = coord + vec3(dtW, 0.0, 0.0);
-myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
-#if defined(APPLY_PCF3x3)
-coord2 = coord + vec3(-dtW, 0.0, 0.0);
-myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
-coord2 = coord + vec3(-dtW, -dtH, 0.0);
-myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ myhalf4 tempColor;
-coord2 = coord + vec3(0.0, -dtH, 0.0);
-myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
-coord2 = coord + vec3(dtW, -dtH, 0.0);
-myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
-coord2 = coord + vec3(-dtW, dtH, 0.0);
-myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
-shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11);
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25);
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
#else
-shadow = shadow0;
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
#endif
+#endif // APPLY_CEL_LIGHT
-float attenuation = float (ProjVector.w) / ProjDistance;
-myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z))
-;compensation = max (compensation, 0.0);
-color = shadow + attenuation + compensation;
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
-gl_FragColor = vec4(vec3(color),1.0);
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-varying vec4 ProjVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-void main(void)
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-gl_Position = ftransform();
-ProjVector = textureMatrix * gl_Vertex;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-#ifdef FRAGMENT_SHADER
-// Fragment shader
-uniform myhalf3 LightAmbient;
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-uniform float TextureWidth, TextureHeight;
-uniform float ProjDistance;
-uniform sampler2DShadow ShadowmapTexture;
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
void main(void)
{
-myhalf color = myhalf(1.0);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
-if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance)
-discard;
+ TransformVerts(Position, Normal, TexCoord);
-float dtW = 1.0 / TextureWidth;
-float dtH = 1.0 / TextureHeight;
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
-vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);
-coord = (coord + vec3 (1.0)) * vec3 (0.5);
-coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));
-coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));
-coord.r = float (clamp (float(coord.r), 0.0, 1.0));
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
-myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r);
-myhalf shadow = shadow0;
+ qf_FrontColor = vec4(outColor);
-#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
-vec3 coord2 = coord + vec3(0.0, dtH, 0.0);
-myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
-coord2 = coord + vec3(dtW, dtH, 0.0);
-myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
-coord2 = coord + vec3(dtW, 0.0, 0.0);
-myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ myhalf4 tempColor;
-#if defined(APPLY_PCF3x3)
-coord2 = coord + vec3(-dtW, 0.0, 0.0);
-myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
-coord2 = coord + vec3(-dtW, -dtH, 0.0);
-myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
-coord2 = coord + vec3(0.0, -dtH, 0.0);
-myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
-coord2 = coord + vec3(dtW, -dtH, 0.0);
-myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
-coord2 = coord + vec3(-dtW, dtH, 0.0);
-myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
-shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11);
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25);
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
#else
-shadow = shadow0;
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
#endif
-float attenuation = float (ProjVector.w) / ProjDistance;
-myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z))
-;compensation = max (compensation, 0.0);
-color = shadow + attenuation + compensation;
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
-gl_FragColor = vec4(vec3(color),1.0);
+ qf_FragColor = vec4(outColor);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/190.shader_test b/shaders/warsow/190.shader_test
new file mode 100644
index 0000000..01fad34
--- /dev/null
+++ b/shaders/warsow/190.shader_test
@@ -0,0 +1,2061 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 8
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/193.shader_test b/shaders/warsow/193.shader_test
new file mode 100644
index 0000000..5b5950a
--- /dev/null
+++ b/shaders/warsow/193.shader_test
@@ -0,0 +1,1753 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/196.shader_test b/shaders/warsow/196.shader_test
new file mode 100644
index 0000000..86d5cfd
--- /dev/null
+++ b/shaders/warsow/196.shader_test
@@ -0,0 +1,1675 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 4
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 4
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/199.shader_test b/shaders/warsow/199.shader_test
new file mode 100644
index 0000000..9c86962
--- /dev/null
+++ b/shaders/warsow/199.shader_test
@@ -0,0 +1,1241 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform float u_OutlineHeight;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
+#endif
+
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
+#endif
+ qf_FragColor = vec4(qf_FrontColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform float u_OutlineHeight;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
+#endif
+
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
+#endif
+ qf_FragColor = vec4(qf_FrontColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/202.shader_test b/shaders/warsow/202.shader_test
new file mode 100644
index 0000000..7700177
--- /dev/null
+++ b/shaders/warsow/202.shader_test
@@ -0,0 +1,1755 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_DLIGHTS 4
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/205.shader_test b/shaders/warsow/205.shader_test
new file mode 100644
index 0000000..37d0f14
--- /dev/null
+++ b/shaders/warsow/205.shader_test
@@ -0,0 +1,2084 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+t = sin(TexCoord.s * 4.000000 + u_QF_ShaderTime * -1.500000);
+Position.xyz += max (-1.0 + 1.000000, t) * 7.000000 * Normal.xyz;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/208.shader_test b/shaders/warsow/208.shader_test
new file mode 100644
index 0000000..ea7b0d1
--- /dev/null
+++ b/shaders/warsow/208.shader_test
@@ -0,0 +1,1698 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+t = sin(TexCoord.s * 4.000000 + u_QF_ShaderTime * -1.500000);
+Position.xyz += max (-1.0 + 1.000000, t) * 7.000000 * Normal.xyz;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/211.shader_test b/shaders/warsow/211.shader_test
new file mode 100644
index 0000000..ed510d6
--- /dev/null
+++ b/shaders/warsow/211.shader_test
@@ -0,0 +1,1793 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+// local sprite axes
+right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide;
+up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw);
+
+// mid of quad to camera vector
+dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz;
+
+// filter any longest-axis-parts off the camera-direction
+forward = normalize(dist - up * dot(dist, up));
+
+// the right axis vector as it should be to face the camera
+newright = cross(up, forward);
+
+// rotate the quad vertex around the up axis vector
+t = dot(right, Position.xyz - a_SpritePoint.xyz);
+Position.xyz += t * (newright - right);
+Normal.xyz = forward;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/214.shader_test b/shaders/warsow/214.shader_test
new file mode 100644
index 0000000..e538a2f
--- /dev/null
+++ b/shaders/warsow/214.shader_test
@@ -0,0 +1,1784 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+right = (1.0 - step(0.5, TexCoord.s) * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide;
+;up = (1.0 - step(0.5, TexCoord.t) * 2.0) * u_QF_ViewAxis[2];
+forward = -1.0 * u_QF_ViewAxis[0];
+Position.xyz = a_SpritePoint.xyz + (right + up) * a_SpritePoint.w;
+Normal.xyz = forward;
+TexCoord.st = vec2(step(0.5, TexCoord.s),step(0.5, TexCoord.t));
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/217.shader_test b/shaders/warsow/217.shader_test
new file mode 100644
index 0000000..7114b78
--- /dev/null
+++ b/shaders/warsow/217.shader_test
@@ -0,0 +1,1782 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+right = (1.0 - step(0.5, TexCoord.s) * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide;
+;up = (1.0 - step(0.5, TexCoord.t) * 2.0) * u_QF_ViewAxis[2];
+forward = -1.0 * u_QF_ViewAxis[0];
+Position.xyz = a_SpritePoint.xyz + (right + up) * a_SpritePoint.w;
+Normal.xyz = forward;
+TexCoord.st = vec2(step(0.5, TexCoord.s),step(0.5, TexCoord.t));
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/22.shader_test b/shaders/warsow/22.shader_test
index b4f6f7c..ced0b98 100644
--- a/shaders/warsow/22.shader_test
+++ b/shaders/warsow/22.shader_test
@@ -1,101 +1,1107 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 ProjVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float OutlineHeight;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-vec4 n = vec4(gl_Normal.xyz, 0.0);
-vec4 v = vec4(gl_Vertex) + n * OutlineHeight;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-gl_Position = gl_ModelViewProjectionMatrix * v;
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * v;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform float OutlineCutOff;
+vec4 DQReal1, DQDual1;
+float scale;
-void main(void)
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_OUTLINES_CUTOFF
-if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff))
-discard;
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_FragColor = vec4 (gl_Color);
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
}
-#endif // FRAGMENT_SHADER
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-varying vec4 ProjVector;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-uniform float OutlineHeight;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-void main(void)
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+struct Fog
{
-gl_FrontColor = gl_Color;
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-vec4 n = vec4(gl_Normal.xyz, 0.0);
-vec4 v = vec4(gl_Vertex) + n * OutlineHeight;
+uniform Fog u_Fog;
-gl_Position = gl_ModelViewProjectionMatrix * v;
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * v;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+qf_varying vec2 v_FogCoord;
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ FogGen(Position, v_FogCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform float OutlineCutOff;
-
void main(void)
{
+ float fogDensity = FogDensity(v_FogCoord);
+ qf_FragColor = vec4(u_Fog.Color, fogDensity);
+}
+
+#endif // FRAGMENT_SHADER
-#ifdef APPLY_OUTLINES_CUTOFF
-if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff))
-discard;
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
#endif
-gl_FragColor = vec4 (gl_Color);
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+qf_varying vec2 v_FogCoord;
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ FogGen(Position, v_FogCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+void main(void)
+{
+ float fogDensity = FogDensity(v_FogCoord);
+ qf_FragColor = vec4(u_Fog.Color, fogDensity);
}
#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/220.shader_test b/shaders/warsow/220.shader_test
new file mode 100644
index 0000000..3817587
--- /dev/null
+++ b/shaders/warsow/220.shader_test
@@ -0,0 +1,1784 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_CONST
+#define APPLY_ALPHA_DISTANCERAMP
+#define APPLY_AUTOSPRITE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+right = (1.0 - step(0.5, TexCoord.s) * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide;
+;up = (1.0 - step(0.5, TexCoord.t) * 2.0) * u_QF_ViewAxis[2];
+forward = -1.0 * u_QF_ViewAxis[0];
+Position.xyz = a_SpritePoint.xyz + (right + up) * a_SpritePoint.w;
+Normal.xyz = forward;
+TexCoord.st = vec2(step(0.5, TexCoord.s),step(0.5, TexCoord.t));
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_CONST
+#define APPLY_ALPHA_DISTANCERAMP
+#define APPLY_AUTOSPRITE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/223.shader_test b/shaders/warsow/223.shader_test
new file mode 100644
index 0000000..9b48bba
--- /dev/null
+++ b/shaders/warsow/223.shader_test
@@ -0,0 +1,1797 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+#define APPLY_SOFT_PARTICLE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+// local sprite axes
+right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide;
+up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw);
+
+// mid of quad to camera vector
+dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz;
+
+// filter any longest-axis-parts off the camera-direction
+forward = normalize(dist - up * dot(dist, up));
+
+// the right axis vector as it should be to face the camera
+newright = cross(up, forward);
+
+// rotate the quad vertex around the up axis vector
+t = dot(right, Position.xyz - a_SpritePoint.xyz);
+Position.xyz += t * (newright - right);
+Normal.xyz = forward;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/226.shader_test b/shaders/warsow/226.shader_test
new file mode 100644
index 0000000..0e5f99e
--- /dev/null
+++ b/shaders/warsow/226.shader_test
@@ -0,0 +1,1784 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_AUTOSPRITE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+right = (1.0 - TexCoord.s * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide;
+;up = (1.0 - TexCoord.t * 2.0) * u_QF_ViewAxis[2];
+forward = -1.0 * u_QF_ViewAxis[0];
+// prevent the particle from disappearing at large distances
+t = dot(a_SpritePoint.xyz + u_QF_EntityOrigin - u_QF_ViewOrigin, u_QF_ViewAxis[0]);
+t = 1.5 + step(20.0, t) * t * 0.006;
+Position.xyz = a_SpritePoint.xyz + (right + up) * t * a_SpritePoint.w;
+Normal.xyz = forward;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_AUTOSPRITE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/229.shader_test b/shaders/warsow/229.shader_test
new file mode 100644
index 0000000..12a6a93
--- /dev/null
+++ b/shaders/warsow/229.shader_test
@@ -0,0 +1,1795 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+// local sprite axes
+right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide;
+up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw);
+
+// mid of quad to camera vector
+dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz;
+
+// filter any longest-axis-parts off the camera-direction
+forward = normalize(dist - up * dot(dist, up));
+
+// the right axis vector as it should be to face the camera
+newright = cross(up, forward);
+
+// rotate the quad vertex around the up axis vector
+t = dot(right, Position.xyz - a_SpritePoint.xyz);
+Position.xyz += t * (newright - right);
+Normal.xyz = forward;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/232.shader_test b/shaders/warsow/232.shader_test
new file mode 100644
index 0000000..f4179af
--- /dev/null
+++ b/shaders/warsow/232.shader_test
@@ -0,0 +1,1784 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+right = (1.0 - TexCoord.s * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide;
+;up = (1.0 - TexCoord.t * 2.0) * u_QF_ViewAxis[2];
+forward = -1.0 * u_QF_ViewAxis[0];
+// prevent the particle from disappearing at large distances
+t = dot(a_SpritePoint.xyz + u_QF_EntityOrigin - u_QF_ViewOrigin, u_QF_ViewAxis[0]);
+t = 1.5 + step(20.0, t) * t * 0.006;
+Position.xyz = a_SpritePoint.xyz + (right + up) * t * a_SpritePoint.w;
+Normal.xyz = forward;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/235.shader_test b/shaders/warsow/235.shader_test
new file mode 100644
index 0000000..88557ad
--- /dev/null
+++ b/shaders/warsow/235.shader_test
@@ -0,0 +1,2063 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/238.shader_test b/shaders/warsow/238.shader_test
new file mode 100644
index 0000000..ebe45c8
--- /dev/null
+++ b/shaders/warsow/238.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define NUM_DLIGHTS 4
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/241.shader_test b/shaders/warsow/241.shader_test
new file mode 100644
index 0000000..b1f3a91
--- /dev/null
+++ b/shaders/warsow/241.shader_test
@@ -0,0 +1,1421 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/244.shader_test b/shaders/warsow/244.shader_test
new file mode 100644
index 0000000..8688157
--- /dev/null
+++ b/shaders/warsow/244.shader_test
@@ -0,0 +1,1421 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+qf_varying vec3 v_TexCoordCube;
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+uniform mat4 u_ReflectionTexMatrix;
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#ifdef APPLY_FOG_COLOR
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+ v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_BaseTexture;
+uniform samplerCube u_CelShadeTexture;
+
+#ifdef APPLY_DIFFUSE
+uniform sampler2D u_DiffuseTexture;
+#endif
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+#ifdef APPLY_STRIPES
+uniform sampler2D u_StripesTexture;
+#endif
+#ifdef APPLY_CEL_LIGHT
+uniform samplerCube u_CelLightTexture;
+#endif
+
+void main(void)
+{
+ myhalf4 inColor = myhalf4(qf_FrontColor);
+
+ myhalf4 tempColor;
+
+ myhalf4 outColor;
+ outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+
+#ifdef APPLY_ENTITY_DECAL
+#ifdef APPLY_ENTITY_DECAL_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_ENTITY_DECAL
+
+#ifdef APPLY_DIFFUSE
+ outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord));
+#endif
+
+ outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube));
+
+#ifdef APPLY_STRIPES
+#ifdef APPLY_STRIPES_ADD
+ outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_STRIPES_ADD
+
+#ifdef APPLY_CEL_LIGHT
+#ifdef APPLY_CEL_LIGHT_ADD
+ outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+#else
+ tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_CEL_LIGHT
+
+#ifdef APPLY_DECAL
+#ifdef APPLY_DECAL_ADD
+ outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+#else
+ tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a);
+#endif
+#endif // APPLY_DECAL
+
+ outColor = myhalf4(inColor * outColor);
+
+#ifdef APPLY_GREYSCALE
+ outColor.rgb = Greyscale(outColor.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(outColor);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/247.shader_test b/shaders/warsow/247.shader_test
new file mode 100644
index 0000000..33c4793
--- /dev/null
+++ b/shaders/warsow/247.shader_test
@@ -0,0 +1,1675 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/25.shader_test b/shaders/warsow/25.shader_test
index 7b223e1..7ad57db 100644
--- a/shaders/warsow/25.shader_test
+++ b/shaders/warsow/25.shader_test
@@ -1,132 +1,5295 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec2 TexCoord;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float TurbAmplitude, TurbPhase;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-vec4 turb;
-turb = vec4(gl_MultiTexCoord0);
-turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI );
-turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI );
-TexCoord = vec2(gl_TextureMatrix[0] * turb);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-gl_Position = ftransform();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+qf_varying vec2 v_TexCoord;
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+void main(void)
+{
+ gl_Position = u_ModelViewProjectionMatrix * a_Position;
+ v_TexCoord = a_TexCoord;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform sampler2D BaseTexture;
+#define FXAA_PC 1
+#if QF_GLSL_VERSION >= 130
+# define FXAA_GLSL_130 1
+#else
+# define FXAA_GLSL_120 1
+#endif
+# ifdef GL_ARB_gpu_shader5
+# extension GL_ARB_gpu_shader5 : enable
+# endif
+#define FXAA_GREEN_AS_LUMA 1
+#define FXAA_QUALITY_X_PRESET 23
+
+uniform sampler2D u_BaseTexture;
+
+#ifdef GL_ARB_gpu_shader5
+/*============================================================================
+
+
+ NVIDIA FXAA 3.11 by TIMOTHY LOTTES
+
+
+------------------------------------------------------------------------------
+COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED.
+------------------------------------------------------------------------------
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
+*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
+OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
+LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION,
+OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE
+THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+------------------------------------------------------------------------------
+ INTEGRATION CHECKLIST
+------------------------------------------------------------------------------
+(1.)
+In the shader source, setup defines for the desired configuration.
+When providing multiple shaders (for different presets),
+simply setup the defines differently in multiple files.
+Example,
+
+ #define FXAA_PC 1
+ #define FXAA_HLSL_5 1
+ #define FXAA_QUALITY_X_PRESET 12
+
+Or,
+
+ #define FXAA_360 1
+
+Or,
+
+ #define FXAA_PS3 1
+
+Etc.
+
+(2.)
+Then include this file,
+
+ #include "Fxaa3_11.h"
+
+(3.)
+Then call the FXAA pixel shader from within your desired shader.
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+As for FXAA 3.11 all inputs for all shaders are the same
+to enable easy porting between platforms.
+
+ return FxaaPixelShader(...);
+
+(4.)
+Insure pass prior to FXAA outputs RGBL (see next section).
+Or use,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+(5.)
+Setup engine to provide the following constants
+which are used in the FxaaPixelShader() inputs,
+
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+
+(6.)
+Have FXAA vertex shader run as a full screen triangle,
+and output "pos" and "fxaaConsolePosPos"
+such that inputs in the pixel shader provide,
+
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+
+ // {xy_X_} = upper left of pixel
+ // {_X_zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+
+(7.)
+Insure the texture sampler(s) used by FXAA are set to bilinear filtering.
+
+
+------------------------------------------------------------------------------
+ INTEGRATION - RGBL AND COLORSPACE
+------------------------------------------------------------------------------
+FXAA3 requires RGBL as input unless the following is set,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+In which case the engine uses green in place of luma,
+and requires RGB input is in a non-linear colorspace.
+
+RGB should be LDR (low dynamic range).
+Specifically do FXAA after tonemapping.
+
+RGB data as returned by a texture fetch can be non-linear,
+or linear when FXAA_GREEN_AS_LUMA is not set.
+Note an "sRGB format" texture counts as linear,
+because the result of a texture fetch is linear data.
+Regular "RGBA8" textures in the sRGB colorspace are non-linear.
+
+If FXAA_GREEN_AS_LUMA is not set,
+luma must be stored in the alpha channel prior to running FXAA.
+This luma should be in a perceptual space (could be gamma 2.0).
+Example pass before FXAA where output is gamma 2.0 encoded,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma
+ return color;
+
+Another example where output is linear encoded,
+say for instance writing to an sRGB formated render target,
+where the render target does the conversion back to sRGB after blending,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma
+ return color;
+
+Getting luma correct is required for the algorithm to work correctly.
+
+
+------------------------------------------------------------------------------
+ BEING LINEARLY CORRECT?
+------------------------------------------------------------------------------
+Applying FXAA to a framebuffer with linear RGB color will look worse.
+This is very counter intuitive, but happends to be true in this case.
+The reason is because dithering artifacts will be more visiable
+in a linear colorspace.
+
+
+------------------------------------------------------------------------------
+ COMPLEX INTEGRATION
+------------------------------------------------------------------------------
+Q. What if the engine is blending into RGB before wanting to run FXAA?
+
+A. In the last opaque pass prior to FXAA,
+ have the pass write out luma into alpha.
+ Then blend into RGB only.
+ FXAA should be able to run ok
+ assuming the blending pass did not any add aliasing.
+ This should be the common case for particles and common blending passes.
+
+A. Or use FXAA_GREEN_AS_LUMA.
+
+============================================================================*/
+
+/*============================================================================
+
+ INTEGRATION KNOBS
+
+============================================================================*/
+//
+// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).
+// FXAA_360_OPT is a prototype for the new optimized 360 version.
+//
+// 1 = Use API.
+// 0 = Don't use API.
+//
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PS3
+ #define FXAA_PS3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360
+ #define FXAA_360 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360_OPT
+ #define FXAA_360_OPT 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_PC
+ //
+ // FXAA Quality
+ // The high quality PC algorithm.
+ //
+ #define FXAA_PC 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PC_CONSOLE
+ //
+ // The console algorithm for PC is included
+ // for developers targeting really low spec machines.
+ // Likely better to just run FXAA_PC, and use a really low preset.
+ //
+ #define FXAA_PC_CONSOLE 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_120
+ #define FXAA_GLSL_120 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_130
+ #define FXAA_GLSL_130 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_3
+ #define FXAA_HLSL_3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_4
+ #define FXAA_HLSL_4 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_5
+ #define FXAA_HLSL_5 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_GREEN_AS_LUMA
+ //
+ // For those using non-linear color,
+ // and either not able to get luma in alpha, or not wanting to,
+ // this enables FXAA to run using green as a proxy for luma.
+ // So with this enabled, no need to pack luma in alpha.
+ //
+ // This will turn off AA on anything which lacks some amount of green.
+ // Pure red and blue or combination of only R and B, will get no AA.
+ //
+ // Might want to lower the settings for both,
+ // fxaaConsoleEdgeThresholdMin
+ // fxaaQualityEdgeThresholdMin
+ // In order to insure AA does not get turned off on colors
+ // which contain a minor amount of green.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_GREEN_AS_LUMA 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_EARLY_EXIT
+ //
+ // Controls algorithm's early exit path.
+ // On PS3 turning this ON adds 2 cycles to the shader.
+ // On 360 turning this OFF adds 10ths of a millisecond to the shader.
+ // Turning this off on console will result in a more blurry image.
+ // So this defaults to on.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_EARLY_EXIT 1
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_DISCARD
+ //
+ // Only valid for PC OpenGL currently.
+ // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
+ //
+ // 1 = Use discard on pixels which don't need AA.
+ // For APIs which enable concurrent TEX+ROP from same surface.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ //
+ #define FXAA_DISCARD 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_FAST_PIXEL_OFFSET
+ //
+ // Used for GLSL 120 only.
+ //
+ // 1 = GL API supports fast pixel offsets
+ // 0 = do not use fast pixel offsets
+ //
+ #ifdef GL_EXT_gpu_shader4
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifndef FXAA_FAST_PIXEL_OFFSET
+ #define FXAA_FAST_PIXEL_OFFSET 0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GATHER4_ALPHA
+ //
+ // 1 = API supports gather4 on alpha channel.
+ // 0 = API does not support gather4 on alpha channel.
+ //
+ #if (FXAA_HLSL_5 == 1)
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#endif
+
+/*============================================================================
+ FXAA CONSOLE PS3 - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS
+ //
+ // Consoles the sharpness of edges on PS3 only.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 8.0 is sharper
+ // 4.0 is softer
+ // 2.0 is really soft (good for vector graphics inputs)
+ //
+ #if 1
+ #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 8.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 4.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 2.0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD
+ //
+ // Only effects PS3.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 0.25 and 0.125.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 0.125 leaves less aliasing, but is softer
+ // 0.25 leaves more aliasing, and is sharper
+ //
+ #if 1
+ #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.125
+ #else
+ #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.25
+ #endif
+#endif
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+------------------------------------------------------------------------------
+NOTE the other tuning knobs are now in the shader function inputs!
+============================================================================*/
+#ifndef FXAA_QUALITY_X_PRESET
+ //
+ // Choose the quality preset.
+ // This needs to be compiled into the shader as it effects code.
+ // Best option to include multiple presets is to
+ // in each shader define the preset, then include this file.
+ //
+ // OPTIONS
+ // -----------------------------------------------------------------------
+ // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
+ // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
+ // 39 - no dither, very expensive
+ //
+ // NOTES
+ // -----------------------------------------------------------------------
+ // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
+ // 13 = about same speed as FXAA 3.9 and better than 12
+ // 23 = closest to FXAA 3.9 visually and performance wise
+ // _ = the lowest digit is directly related to performance
+ // _ = the highest digit is directly related to style
+ //
+ #define FXAA_QUALITY_X_PRESET 12
+#endif
+
+
+/*============================================================================
+
+ FXAA QUALITY - PRESETS
+
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY_X_PRESET == 10)
+ #define FXAA_QUALITY_X_PS 3
+ #define FXAA_QUALITY_X_P0 1.5
+ #define FXAA_QUALITY_X_P1 3.0
+ #define FXAA_QUALITY_X_P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 11)
+ #define FXAA_QUALITY_X_PS 4
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 3.0
+ #define FXAA_QUALITY_X_P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 12)
+ #define FXAA_QUALITY_X_PS 5
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 4.0
+ #define FXAA_QUALITY_X_P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 13)
+ #define FXAA_QUALITY_X_PS 6
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 4.0
+ #define FXAA_QUALITY_X_P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 14)
+ #define FXAA_QUALITY_X_PS 7
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 4.0
+ #define FXAA_QUALITY_X_P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 15)
+ #define FXAA_QUALITY_X_PS 8
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 4.0
+ #define FXAA_QUALITY_X_P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY_X_PRESET == 20)
+ #define FXAA_QUALITY_X_PS 3
+ #define FXAA_QUALITY_X_P0 1.5
+ #define FXAA_QUALITY_X_P1 2.0
+ #define FXAA_QUALITY_X_P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 21)
+ #define FXAA_QUALITY_X_PS 4
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 22)
+ #define FXAA_QUALITY_X_PS 5
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 23)
+ #define FXAA_QUALITY_X_PS 6
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 24)
+ #define FXAA_QUALITY_X_PS 7
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 3.0
+ #define FXAA_QUALITY_X_P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 25)
+ #define FXAA_QUALITY_X_PS 8
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 4.0
+ #define FXAA_QUALITY_X_P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 26)
+ #define FXAA_QUALITY_X_PS 9
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 4.0
+ #define FXAA_QUALITY_X_P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 27)
+ #define FXAA_QUALITY_X_PS 10
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 4.0
+ #define FXAA_QUALITY_X_P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 28)
+ #define FXAA_QUALITY_X_PS 11
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 2.0
+ #define FXAA_QUALITY_X_P9 4.0
+ #define FXAA_QUALITY_X_P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 29)
+ #define FXAA_QUALITY_X_PS 12
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 2.0
+ #define FXAA_QUALITY_X_P9 2.0
+ #define FXAA_QUALITY_X_P10 4.0
+ #define FXAA_QUALITY_X_P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY_X_PRESET == 39)
+ #define FXAA_QUALITY_X_PS 12
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.0
+ #define FXAA_QUALITY_X_P2 1.0
+ #define FXAA_QUALITY_X_P3 1.0
+ #define FXAA_QUALITY_X_P4 1.0
+ #define FXAA_QUALITY_X_P5 1.5
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 2.0
+ #define FXAA_QUALITY_X_P9 2.0
+ #define FXAA_QUALITY_X_P10 4.0
+ #define FXAA_QUALITY_X_P11 8.0
+#endif
+
+
+
+/*============================================================================
+
+ API PORTING
+
+============================================================================*/
+#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)
+ #define FxaaBool bool
+ #define FxaaDiscard discard
+ #define FxaaFloat float
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaHalf float
+ #define FxaaHalf2 vec2
+ #define FxaaHalf3 vec3
+ #define FxaaHalf4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaTex sampler2D
+#else
+ #define FxaaBool bool
+ #define FxaaDiscard clip(-1)
+ #define FxaaFloat float
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaHalf half
+ #define FxaaHalf2 half2
+ #define FxaaHalf3 half3
+ #define FxaaHalf4 half4
+ #define FxaaSat(x) saturate(x)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_120 == 1)
+ // Requires,
+ // #version 120
+ // And at least,
+ // #extension GL_EXT_gpu_shader4 : enable
+ // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
+ #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
+ #if (FXAA_FAST_PIXEL_OFFSET == 1)
+ #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
+ #else
+ #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
+ #endif
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_130 == 1)
+ // Requires "#version 130" or better
+ #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1)
+ #define FxaaInt2 float2
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
+ #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_4 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_5 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+ #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)
+ #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)
+ #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)
+ #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)
+#endif
+
+
+/*============================================================================
+ GREEN AS LUMA OPTION SUPPORT FUNCTION
+============================================================================*/
+#if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
+#else
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+#if (FXAA_PC == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+ //
+ // Used only for FXAA Console, and not used on the 360 version.
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy_X_} = upper left of pixel
+ // {_X_zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ // if (FXAA_GREEN_AS_LUMA == 0)
+ // {_X__a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 2nd sampler.
+ // This sampler needs to have an exponent bias of -1.
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 3nd sampler.
+ // This sampler needs to have an exponent bias of -2.
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ FxaaFloat2 fxaaQualityRcpFrame,
+ //
+ // Only used on FXAA Console.
+ // This must be from a constant/uniform.
+ // This effects sub-pixel AA quality and inversely sharpness.
+ // Where N ranges between,
+ // N = 0.50 (default)
+ // N = 0.33 (sharper)
+ // {x_X__} = -N/screenWidthInPixels
+ // {_y_X_} = -N/screenHeightInPixels
+ // {_X_z_} = N/screenWidthInPixels
+ // {_X__w} = N/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ //
+ // Only used on FXAA Console.
+ // Not used on 360, but used on PS3 and PC.
+ // This must be from a constant/uniform.
+ // {x_X__} = -2.0/screenWidthInPixels
+ // {_y_X_} = -2.0/screenHeightInPixels
+ // {_X_z_} = 2.0/screenWidthInPixels
+ // {_X__w} = 2.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ //
+ // Only used on FXAA Console.
+ // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.
+ // This must be from a constant/uniform.
+ // {x_X__} = 8.0/screenWidthInPixels
+ // {_y_X_} = 8.0/screenHeightInPixels
+ // {_X_z_} = -4.0/screenWidthInPixels
+ // {_X__w} = -4.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY_X_SUBPIX define.
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ FxaaFloat fxaaQualitySubpix,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ FxaaFloat fxaaQualityEdgeThreshold,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE_X_EDGE_SHARPNESS define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only three safe values here: 2 and 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // For all other platforms can be a non-power of two.
+ // 8.0 is sharper (default!!!)
+ // 4.0 is softer
+ // 2.0 is really soft (good only for vector graphics inputs)
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 1/4 and 1/8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // The console setting has a different mapping than the quality setting.
+ // Other platforms can use other values.
+ // 0.125 leaves less aliasing, but is softer (default!!!)
+ // 0.25 leaves more aliasing, and is sharper
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ // This does not apply to PS3,
+ // PS3 was simplified to avoid more shader instructions.
+ // 0.06 - faster but more aliasing in darks
+ // 0.05 - default
+ // 0.04 - slower and less aliasing in darks
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ //
+ // Extra constants for 360 FXAA Console only.
+ // Use zeros or anything else for other platforms.
+ // These must be in physical constant registers and NOT immedates.
+ // Immedates will result in compiler un-optimizing.
+ // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ #if (FXAA_GATHER4_ALPHA == 1)
+ #if (FXAA_DISCARD == 0)
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ #endif
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
+ #else
+ FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
+ #endif
+ #if (FXAA_DISCARD == 1)
+ #define lumaM luma4A.w
+ #endif
+ #define lumaE luma4A.z
+ #define lumaS luma4A.x
+ #define lumaSE luma4A.y
+ #define lumaNW luma4B.w
+ #define lumaN luma4B.z
+ #define lumaW luma4B.x
+ #else
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat maxSM = max(lumaS, lumaM);
+ FxaaFloat minSM = min(lumaS, lumaM);
+ FxaaFloat maxESM = max(lumaE, maxSM);
+ FxaaFloat minESM = min(lumaE, minSM);
+ FxaaFloat maxWN = max(lumaN, lumaW);
+ FxaaFloat minWN = min(lumaN, lumaW);
+ FxaaFloat rangeMax = max(maxWN, maxESM);
+ FxaaFloat rangeMin = min(minWN, minESM);
+ FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ FxaaFloat range = rangeMax - rangeMin;
+ FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ FxaaBool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit)
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 0)
+ FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #else
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNS = lumaN + lumaS;
+ FxaaFloat lumaWE = lumaW + lumaE;
+ FxaaFloat subpixRcpRange = 1.0/range;
+ FxaaFloat subpixNSWE = lumaNS + lumaWE;
+ FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNESE = lumaNE + lumaSE;
+ FxaaFloat lumaNWNE = lumaNW + lumaNE;
+ FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNWSW = lumaNW + lumaSW;
+ FxaaFloat lumaSWSE = lumaSW + lumaSE;
+ FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
+ FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
+ FxaaBool horzSpan = edgeHorz >= edgeVert;
+ FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat gradientN = lumaN - lumaM;
+ FxaaFloat gradientS = lumaS - lumaM;
+ FxaaFloat lumaNN = lumaN + lumaM;
+ FxaaFloat lumaSS = lumaS + lumaM;
+ FxaaBool pairN = abs(gradientN) >= abs(gradientS);
+ FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ FxaaFloat2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY_X_P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY_X_P0;
+ FxaaFloat2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY_X_P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY_X_P0;
+ FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
+ FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ FxaaFloat subpixE = subpixC * subpixC;
+ FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ FxaaFloat gradientScaled = gradient * 1.0/4.0;
+ FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
+ FxaaFloat subpixF = subpixD * subpixE;
+ FxaaBool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
+ FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P1;
+ FxaaBool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dstN = posM.x - posN.x;
+ FxaaFloat dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ FxaaFloat spanLength = (dstP + dstN);
+ FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ FxaaFloat spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ FxaaBool directionN = dstN < dstP;
+ FxaaFloat dst = min(dstN, dstP);
+ FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
+ FxaaFloat subpixG = subpixF * subpixF;
+ FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ #if (FXAA_DISCARD == 1)
+ return FxaaTexTop(tex, posM);
+ #else
+ return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
+ #endif
+}
+/*==========================================================================*/
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - PC VERSION
+
+------------------------------------------------------------------------------
+Instead of using this on PC, I'd suggest just using FXAA Quality with
+ #define FXAA_QUALITY_X_PRESET 10
+Or
+ #define FXAA_QUALITY_X_PRESET 20
+Either are higher qualilty and almost as fast as this on modern PC GPUs.
+============================================================================*/
+#if (FXAA_PC_CONSOLE == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));
+ FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));
+ FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));
+ FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat lumaM = rgbyM.w;
+ #else
+ FxaaFloat lumaM = rgbyM.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);
+ lumaNe += 1.0/384.0;
+ FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);
+ FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
+ FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMinM = min(lumaMin, lumaM);
+ FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);
+ FxaaFloat lumaMaxM = max(lumaMax, lumaM);
+ FxaaFloat dirSwMinusNe = lumaSw - lumaNe;
+ FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;
+ FxaaFloat dirSeMinusNw = lumaSe - lumaNw;
+ if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir;
+ dir.x = dirSwMinusNe + dirSeMinusNw;
+ dir.y = dirSwMinusNe - dirSeMinusNw;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir1 = normalize(dir.xy);
+ FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);
+ FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;
+ FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);
+ FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;
+ FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
+ #else
+ FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);
+ #endif
+ if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;
+ return rgbyB; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - 360 PIXEL SHADER
+
+------------------------------------------------------------------------------
+This optimized version thanks to suggestions from Andy Luedke.
+Should be fully tex bound in all cases.
+As of the FXAA 3.11 release, I have still not tested this code,
+however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10.
+And note this is replacing the old unoptimized version.
+If it does not work, please let me know so I can fix it.
+============================================================================*/
+#if (FXAA_360 == 1)
+/*--------------------------------------------------------------------------*/
+ [reduceTempRegUsage(4)]
+float4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ float4 lumaNwNeSwSe;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ asm {
+ tfetch2D lumaNwNeSwSe.w_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._w_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X_w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X__w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #else
+ asm {
+ tfetch2D lumaNwNeSwSe.y_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._y_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X_y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X__y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #endif
+/*--------------------------------------------------------------------------*/
+ lumaNwNeSwSe.y += 1.0/384.0;
+ float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);
+ float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);
+/*--------------------------------------------------------------------------*/
+ float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ float lumaMinM = min(lumaMin, rgbyM.w);
+ float lumaMaxM = max(lumaMax, rgbyM.w);
+ #else
+ float lumaMinM = min(lumaMin, rgbyM.y);
+ float lumaMaxM = max(lumaMax, rgbyM.y);
+ #endif
+ if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ float2 dir;
+ dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx);
+ dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy);
+ dir = normalize(dir);
+/*--------------------------------------------------------------------------*/
+ float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw;
+/*--------------------------------------------------------------------------*/
+ float4 dir2;
+ float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness;
+ dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5);
+ dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0));
+ float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0));
+ float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0));
+ float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+ float4 rgbyA = rgbyN1 + rgbyP1;
+ float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB;
+ rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA;
+ return rgbyR; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)
+
+==============================================================================
+The code below does not exactly match the assembly.
+I have a feeling that 12 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h0.w(TRUE), v5.xwxx, #0
+ 6: addh h0.z(TRUE), -h2, h0.w
+ 7: texpkb h1.w(TRUE), v5, #0
+ 9: addh h0.x(TRUE), h0.z, -h1.w
+ 10: addh h3.w(TRUE), h0.z, h1
+ 11: texpkb h2.w(TRUE), v5.zwzz, #0
+ 13: addh h0.z(TRUE), h3.w, -h2.w
+ 14: addh h0.x(TRUE), h2.w, h0
+ 15: nrmh h1.xz(TRUE), h0_n
+ 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|
+ 17: maxh h4.w(TRUE), h0, h1
+ 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n
+ 19: movr r1.zw(TRUE), v4.xxxy
+ 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww
+ 22: minh h5.w(TRUE), h0, h1
+ 23: texpkb h0(TRUE), r2.xzxx, #0
+ 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1
+ 27: maxh h4.x(TRUE), h2.z, h2.w
+ 28: texpkb h1(TRUE), r0.zwzz, #0
+ 30: addh_d2 h1(TRUE), h0, h1
+ 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 33: texpkb h0(TRUE), r0, #0
+ 35: minh h4.z(TRUE), h2, h2.w
+ 36: fenct TRUE
+ 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 39: texpkb h2(TRUE), r1, #0
+ 41: addh_d2 h0(TRUE), h0, h2
+ 42: maxh h2.w(TRUE), h4, h4.x
+ 43: minh h2.x(TRUE), h5.w, h4.z
+ 44: addh_d2 h0(TRUE), h0, h1
+ 45: slth h2.x(TRUE), h0.w, h2
+ 46: sgth h2.w(TRUE), h0, h2
+ 47: movh h0(TRUE), h0
+ 48: addx.c0 rc(TRUE), h2, h2.w
+ 49: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---;
+ | SCB1 | add | 10: ADDh h3.w, h0.---z, h1;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h2.w---, h0;
+ | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-;
+ | | |
+ 5 | SCT1 | mov | 15: NRMh h1.xz, h0;
+ | SRB | nrm | 15: NRMh h1.xz, h0;
+ | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|;
+ | SCB1 | max | 17: MAXh h4.w, h0, h1;
+ | | |
+ 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0;
+ | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy;
+ | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-;
+ | SCB1 | min | 22: MINh h5.w, h0, h1;
+ | | |
+ 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---;
+ | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1;
+ | | |
+ 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | SCB0/1 | add | 30: ADDh/2 h1, h0, h1;
+ | | |
+ 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB1 | min | 35: MINh h4.z, h2, h2.--w-;
+ | | |
+ 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | SCB0/1 | add | 41: ADDh/2 h0, h0, h2;
+ | | |
+ 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---;
+ | SCT1 | max | 42: MAXh h2.w, h4, h4.---x;
+ | SCB0/1 | add | 44: ADDh/2 h0, h0, h1;
+ | | |
+ 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2;
+ | SCT1 | set | 46: SGTh h2.w, h0, h2;
+ | SCB0/1 | mul | 47: MOVh h0, h0;
+ | | |
+ 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---;
+ | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 0% 0% 50%
+ 6: 100% 0% 75%
+ 7: 0% 100% 75%
+ 8: 0% 100% 100%
+ 9: 0% 100% 25%
+ 10: 0% 100% 100%
+ 11: 50% 0% 100%
+ 12: 50% 0% 100%
+ 13: 25% 0% 100%
+
+MEAN: 17% 61% 67%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 0% 100%
+ 2: 0% 0% 100% 0% 100%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 0% 0% 0% 100% 100%
+ 6: 100% 100% 0% 100% 100%
+ 7: 0% 0% 100% 100% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 0% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 100% 100% 0% 100% 100%
+ 12: 100% 100% 0% 100% 100%
+ 13: 100% 0% 0% 100% 100%
+
+MEAN: 30% 23% 61% 76% 100%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 13 cycles, 3 r regs, 923,076,923 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O3
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 dir;
+ half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ lumaNe.w += half(1.0/512.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+ #else
+ lumaNe.y += half(1.0/512.0);
+ dir.x = -lumaNe.y;
+ dir.z = -lumaNe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+ #else
+ dir.x += lumaSw.y;
+ dir.z += lumaSw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+ #else
+ dir.x -= lumaNw.y;
+ dir.z += lumaNw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+ #else
+ dir.x += lumaSe.y;
+ dir.z -= lumaSe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (7)
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (8)
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (11)
+ // compilier moves these scalar ops up to other cycles
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ #else
+ half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y));
+ half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y));
+ #endif
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (12)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (13)
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)
+
+==============================================================================
+The code mostly matches the assembly.
+I have a feeling that 14 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks).
+Will look at fixing this for FXAA 3.12.
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h1.w(TRUE), v5.xwxx, #0
+ 6: addh h0.x(TRUE), h1.w, -h2.y
+ 7: texpkb h2.w(TRUE), v5.zwzz, #0
+ 9: minh h4.w(TRUE), h2.y, h2
+ 10: maxh h5.x(TRUE), h2.y, h2.w
+ 11: texpkb h0.w(TRUE), v5, #0
+ 13: addh h3.w(TRUE), -h0, h0.x
+ 14: addh h0.x(TRUE), h0.w, h0
+ 15: addh h0.z(TRUE), -h2.w, h0.x
+ 16: addh h0.x(TRUE), h2.w, h3.w
+ 17: minh h5.y(TRUE), h0.w, h1.w
+ 18: nrmh h2.xz(TRUE), h0_n
+ 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|
+ 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w
+ 21: movr r1.zw(TRUE), v4.xxxy
+ 22: maxh h2.w(TRUE), h0, h1
+ 23: fenct TRUE
+ 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 26: texpkb h0(TRUE), r0, #0
+ 28: maxh h5.x(TRUE), h2.w, h5
+ 29: minh h5.w(TRUE), h5.y, h4
+ 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 32: texpkb h2(TRUE), r1, #0
+ 34: addh_d2 h2(TRUE), h0, h2
+ 35: texpkb h1(TRUE), v4, #0
+ 37: maxh h5.y(TRUE), h5.x, h1.w
+ 38: minh h4.w(TRUE), h1, h5
+ 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 41: texpkb h0(TRUE), r0, #0
+ 43: addh_m8 h5.z(TRUE), h5.y, -h4.w
+ 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 46: texpkb h3(TRUE), r2, #0
+ 48: addh_d2 h0(TRUE), h0, h3
+ 49: addh_d2 h3(TRUE), h0, h2
+ 50: movh h0(TRUE), h3
+ 51: slth h3.x(TRUE), h3.w, h5.w
+ 52: sgth h3.w(TRUE), h3, h5.x
+ 53: addx.c0 rc(TRUE), h3.x, h3
+ 54: slth.c0 rc(TRUE), h5.z, h5
+ 55: movh h0(c0.NE.w), h2
+ 56: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---;
+ | SCB1 | min | 9: MINh h4.w, h2.---y, h2;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h0.w---, h0;
+ | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x;
+ | | |
+ 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---;
+ | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-;
+ | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--;
+ | | |
+ 6 | SCT1 | mov | 18: NRMh h2.xz, h0;
+ | SRB | nrm | 18: NRMh h2.xz, h0;
+ | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|;
+ | | |
+ 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--;
+ | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy;
+ | SCB1 | max | 22: MAXh h2.w, h0, h1;
+ | | |
+ 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | SCB0 | max | 28: MAXh h5.x, h2.w---, h5;
+ | SCB1 | min | 29: MINh h5.w, h5.---y, h4;
+ | | |
+ 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | SCB0/1 | add | 34: ADDh/2 h2, h0, h2;
+ | | |
+ 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--;
+ | SCB1 | min | 38: MINh h4.w, h1, h5;
+ | | |
+ 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--;
+ | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--;
+ | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-;
+ | | |
+ 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | SCB0/1 | add | 48: ADDh/2 h0, h0, h3;
+ | | |
+ 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2;
+ | SCB0/1 | mul | 50: MOVh h0, h3;
+ | | |
+ 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---;
+ | SCT1 | set | 52: SGTh h3.w, h3, h5.---x;
+ | SCB0 | set | 54: SLThc0 rc, h5.z---, h5;
+ | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3;
+ | | |
+ 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2;
+ | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 50% 0% 25%
+ 6: 0% 0% 25%
+ 7: 100% 0% 25%
+ 8: 0% 100% 50%
+ 9: 0% 100% 100%
+ 10: 0% 100% 50%
+ 11: 0% 100% 75%
+ 12: 0% 100% 100%
+ 13: 100% 0% 100%
+ 14: 50% 0% 50%
+ 15: 100% 0% 100%
+
+MEAN: 26% 60% 56%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 100% 0%
+ 2: 0% 0% 100% 100% 0%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 100% 100% 0% 100% 0%
+ 6: 0% 0% 0% 0% 100%
+ 7: 100% 100% 0% 0% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 100% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 0% 0% 100% 100% 100%
+ 12: 0% 0% 100% 100% 100%
+ 13: 100% 100% 0% 100% 100%
+ 14: 100% 100% 0% 100% 100%
+ 15: 100% 100% 0% 100% 100%
+
+MEAN: 33% 33% 60% 86% 80%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 15 cycles, 3 r regs, 800,000,000 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O2
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaNe = rgbyNe.w + half(1.0/512.0);
+ #else
+ half lumaNe = rgbyNe.y + half(1.0/512.0);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaSwNegNe = lumaSw.w - lumaNe;
+ #else
+ half lumaSwNegNe = lumaSw.y - lumaNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);
+ half lumaMinNwSw = min(lumaNw.w, lumaSw.w);
+ #else
+ half lumaMaxNwSw = max(lumaNw.y, lumaSw.y);
+ half lumaMinNwSw = min(lumaNw.y, lumaSw.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half dirZ = lumaNw.w + lumaSwNegNe;
+ half dirX = -lumaNw.w + lumaSwNegNe;
+ #else
+ half dirZ = lumaNw.y + lumaSwNegNe;
+ half dirX = -lumaNw.y + lumaSwNegNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half3 dir;
+ dir.y = 0.0;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x = lumaSe.w + dirX;
+ dir.z = -lumaSe.w + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.w);
+ #else
+ dir.x = lumaSe.y + dirX;
+ dir.z = -lumaSe.y + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir).xz;
+ half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (7)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNeSe = max(lumaNe, lumaSe.w);
+ #else
+ half lumaMaxNeSe = max(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (8)
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);
+ half lumaMin = min(lumaMinNwSw, lumaMinNeSe);
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ #else
+ half lumaMaxM = max(lumaMax, rgbyM.y);
+ half lumaMinM = min(lumaMin, rgbyM.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (11)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+// (12)
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (13)
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (14)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+ bool earlyExit = lumaRangeM < lumaMax;
+ bool twoTap = twoTapLt || twoTapGt;
+/*--------------------------------------------------------------------------*/
+// (15)
+ if(twoTap) rgby2 = rgby1;
+ if(earlyExit) rgby2 = rgbyM;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+#else
+#define FXAA_SPAN_MAX 8.0
+#define FXAA_REDUCE_MUL 1.0/8.0
+#define FXAA_REDUCE_MIN 1.0/128.0
+
+vec4 FxaaPixelShader(
+ vec2 pos,
+ vec4 fxaaConsolePosPos,
+ sampler2D tex,
+ sampler2D fxaaConsole360TexExpBiasNegOne,
+ sampler2D fxaaConsole360TexExpBiasNegTwo,
+ vec2 fxaaQualityRcpFrame,
+ vec4 fxaaConsoleRcpFrameOpt,
+ vec4 fxaaConsoleRcpFrameOpt2,
+ vec4 fxaaConsole360RcpFrameOpt2,
+ float fxaaQualitySubpix,
+ float fxaaQualityEdgeThreshold,
+ float fxaaQualityEdgeThresholdMin,
+ float fxaaConsoleEdgeSharpness,
+ float fxaaConsoleEdgeThreshold,
+ float fxaaConsoleEdgeThresholdMin,
+ vec4 fxaaConsole360ConstDir
+) {
+#define Tex() qf_texture(tex, pos).rgb
+#define TexOfs(ofs) qf_texture(tex, pos + ofs).rgb
+#define TexOfsInv(ofs) qf_texture(tex, pos + ofs * fxaaQualityRcpFrame).rgb
+
+ vec3 rgbNW = TexOfsInv(vec2(-1.0,-1.0));
+ vec3 rgbNE = TexOfsInv(vec2(1.0,-1.0));
+ vec3 rgbSW = TexOfsInv(vec2(-1.0,1.0));
+ vec3 rgbSE = TexOfsInv(vec2(1.0,1.0));
+ vec3 rgbM = Tex();
+
+ vec3 luma = vec3(0.299, 0.587, 0.114);
+ float lumaNW = dot(rgbNW, luma);
+ float lumaNE = dot(rgbNE, luma);
+ float lumaSW = dot(rgbSW, luma);
+ float lumaSE = dot(rgbSE, luma);
+ float lumaM = dot(rgbM, luma);
+
+ float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+ float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+ vec2 dir;
+ dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+ dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+ float dirReduce = max(
+ (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
+ FXAA_REDUCE_MIN);
+ float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
+
+ dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
+ max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
+ dir * rcpDirMin)) * fxaaQualityRcpFrame;
+
+ vec3 rgbA = (1.0/2.0) * (
+ TexOfs(dir * (1.0/3.0 - 0.5)) +
+ TexOfs(dir * (2.0/3.0 - 0.5)));
+ vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
+ TexOfs(dir * (0.0/3.0 - 0.5)) +
+ TexOfs(dir * (3.0/3.0 - 0.5)));
+ float lumaB = dot(rgbB, luma);
+
+ if((lumaB < lumaMin) || (lumaB > lumaMax)){
+ return vec4(rgbA, 1.0);
+ }else{
+ return vec4(rgbB, 1.0);
+ }
+}
+
+
+#endif
void main(void)
{
+ // Only used on FXAA Quality.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ float QualitySubpix = 0.75;
-myhalf4 color;
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.033 - very high quality (slower)
+ float QualityEdgeThreshold = 0.166;
+ float QualityEdgeThresholdMin = 0.0;
-color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord));
+ vec4 ConsolePosPos = vec4(0.0,0.0,0.0,0.0);
+ vec4 ConsoleRcpFrameOpt = vec4(0.0,0.0,0.0,0.0);
+ vec4 ConsoleRcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0);
+ vec4 Console360RcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0);
+ float ConsoleEdgeSharpness = 8.0;
+ float ConsoleEdgeThreshold = 0.125;
+ float ConsoleEdgeThresholdMin = 0.05;
+ vec4 Console360ConstDir = vec4(1.0, -1.0, 0.25, -0.25);
-gl_FragColor = vec4(color);
+ qf_FragColor = FxaaPixelShader(v_TexCoord, ConsolePosPos, u_BaseTexture, u_BaseTexture, u_BaseTexture,
+ u_TextureParams.zw, ConsoleRcpFrameOpt, ConsoleRcpFrameOpt2, Console360RcpFrameOpt2,
+ QualitySubpix, QualityEdgeThreshold, QualityEdgeThresholdMin, ConsoleEdgeSharpness,
+ ConsoleEdgeThreshold, ConsoleEdgeThresholdMin, Console360ConstDir);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec2 TexCoord;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float TurbAmplitude, TurbPhase;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-vec4 turb;
-turb = vec4(gl_MultiTexCoord0);
-turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI );
-turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI );
-TexCoord = vec2(gl_TextureMatrix[0] * turb);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-gl_Position = ftransform();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+qf_varying vec2 v_TexCoord;
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+void main(void)
+{
+ gl_Position = u_ModelViewProjectionMatrix * a_Position;
+ v_TexCoord = a_TexCoord;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform sampler2D BaseTexture;
+#define FXAA_PC 1
+#if QF_GLSL_VERSION >= 130
+# define FXAA_GLSL_130 1
+#else
+# define FXAA_GLSL_120 1
+#endif
+# ifdef GL_ARB_gpu_shader5
+# extension GL_ARB_gpu_shader5 : enable
+# endif
+#define FXAA_GREEN_AS_LUMA 1
+#define FXAA_QUALITY_X_PRESET 23
+
+uniform sampler2D u_BaseTexture;
+
+#ifdef GL_ARB_gpu_shader5
+/*============================================================================
+
+
+ NVIDIA FXAA 3.11 by TIMOTHY LOTTES
+
+
+------------------------------------------------------------------------------
+COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED.
+------------------------------------------------------------------------------
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
+*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
+OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
+LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION,
+OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE
+THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+------------------------------------------------------------------------------
+ INTEGRATION CHECKLIST
+------------------------------------------------------------------------------
+(1.)
+In the shader source, setup defines for the desired configuration.
+When providing multiple shaders (for different presets),
+simply setup the defines differently in multiple files.
+Example,
+
+ #define FXAA_PC 1
+ #define FXAA_HLSL_5 1
+ #define FXAA_QUALITY_X_PRESET 12
+
+Or,
+
+ #define FXAA_360 1
+
+Or,
+
+ #define FXAA_PS3 1
+
+Etc.
+
+(2.)
+Then include this file,
+
+ #include "Fxaa3_11.h"
+
+(3.)
+Then call the FXAA pixel shader from within your desired shader.
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+As for FXAA 3.11 all inputs for all shaders are the same
+to enable easy porting between platforms.
+
+ return FxaaPixelShader(...);
+
+(4.)
+Insure pass prior to FXAA outputs RGBL (see next section).
+Or use,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+(5.)
+Setup engine to provide the following constants
+which are used in the FxaaPixelShader() inputs,
+
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+
+(6.)
+Have FXAA vertex shader run as a full screen triangle,
+and output "pos" and "fxaaConsolePosPos"
+such that inputs in the pixel shader provide,
+
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+
+ // {xy_X_} = upper left of pixel
+ // {_X_zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+
+(7.)
+Insure the texture sampler(s) used by FXAA are set to bilinear filtering.
+
+
+------------------------------------------------------------------------------
+ INTEGRATION - RGBL AND COLORSPACE
+------------------------------------------------------------------------------
+FXAA3 requires RGBL as input unless the following is set,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+In which case the engine uses green in place of luma,
+and requires RGB input is in a non-linear colorspace.
+
+RGB should be LDR (low dynamic range).
+Specifically do FXAA after tonemapping.
+
+RGB data as returned by a texture fetch can be non-linear,
+or linear when FXAA_GREEN_AS_LUMA is not set.
+Note an "sRGB format" texture counts as linear,
+because the result of a texture fetch is linear data.
+Regular "RGBA8" textures in the sRGB colorspace are non-linear.
+
+If FXAA_GREEN_AS_LUMA is not set,
+luma must be stored in the alpha channel prior to running FXAA.
+This luma should be in a perceptual space (could be gamma 2.0).
+Example pass before FXAA where output is gamma 2.0 encoded,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma
+ return color;
+
+Another example where output is linear encoded,
+say for instance writing to an sRGB formated render target,
+where the render target does the conversion back to sRGB after blending,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma
+ return color;
+
+Getting luma correct is required for the algorithm to work correctly.
+
+
+------------------------------------------------------------------------------
+ BEING LINEARLY CORRECT?
+------------------------------------------------------------------------------
+Applying FXAA to a framebuffer with linear RGB color will look worse.
+This is very counter intuitive, but happends to be true in this case.
+The reason is because dithering artifacts will be more visiable
+in a linear colorspace.
+
+
+------------------------------------------------------------------------------
+ COMPLEX INTEGRATION
+------------------------------------------------------------------------------
+Q. What if the engine is blending into RGB before wanting to run FXAA?
+
+A. In the last opaque pass prior to FXAA,
+ have the pass write out luma into alpha.
+ Then blend into RGB only.
+ FXAA should be able to run ok
+ assuming the blending pass did not any add aliasing.
+ This should be the common case for particles and common blending passes.
+
+A. Or use FXAA_GREEN_AS_LUMA.
+
+============================================================================*/
+
+/*============================================================================
+
+ INTEGRATION KNOBS
+
+============================================================================*/
+//
+// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).
+// FXAA_360_OPT is a prototype for the new optimized 360 version.
+//
+// 1 = Use API.
+// 0 = Don't use API.
+//
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PS3
+ #define FXAA_PS3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360
+ #define FXAA_360 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360_OPT
+ #define FXAA_360_OPT 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_PC
+ //
+ // FXAA Quality
+ // The high quality PC algorithm.
+ //
+ #define FXAA_PC 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PC_CONSOLE
+ //
+ // The console algorithm for PC is included
+ // for developers targeting really low spec machines.
+ // Likely better to just run FXAA_PC, and use a really low preset.
+ //
+ #define FXAA_PC_CONSOLE 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_120
+ #define FXAA_GLSL_120 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_130
+ #define FXAA_GLSL_130 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_3
+ #define FXAA_HLSL_3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_4
+ #define FXAA_HLSL_4 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_5
+ #define FXAA_HLSL_5 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_GREEN_AS_LUMA
+ //
+ // For those using non-linear color,
+ // and either not able to get luma in alpha, or not wanting to,
+ // this enables FXAA to run using green as a proxy for luma.
+ // So with this enabled, no need to pack luma in alpha.
+ //
+ // This will turn off AA on anything which lacks some amount of green.
+ // Pure red and blue or combination of only R and B, will get no AA.
+ //
+ // Might want to lower the settings for both,
+ // fxaaConsoleEdgeThresholdMin
+ // fxaaQualityEdgeThresholdMin
+ // In order to insure AA does not get turned off on colors
+ // which contain a minor amount of green.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_GREEN_AS_LUMA 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_EARLY_EXIT
+ //
+ // Controls algorithm's early exit path.
+ // On PS3 turning this ON adds 2 cycles to the shader.
+ // On 360 turning this OFF adds 10ths of a millisecond to the shader.
+ // Turning this off on console will result in a more blurry image.
+ // So this defaults to on.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_EARLY_EXIT 1
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_DISCARD
+ //
+ // Only valid for PC OpenGL currently.
+ // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
+ //
+ // 1 = Use discard on pixels which don't need AA.
+ // For APIs which enable concurrent TEX+ROP from same surface.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ //
+ #define FXAA_DISCARD 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_FAST_PIXEL_OFFSET
+ //
+ // Used for GLSL 120 only.
+ //
+ // 1 = GL API supports fast pixel offsets
+ // 0 = do not use fast pixel offsets
+ //
+ #ifdef GL_EXT_gpu_shader4
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifndef FXAA_FAST_PIXEL_OFFSET
+ #define FXAA_FAST_PIXEL_OFFSET 0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GATHER4_ALPHA
+ //
+ // 1 = API supports gather4 on alpha channel.
+ // 0 = API does not support gather4 on alpha channel.
+ //
+ #if (FXAA_HLSL_5 == 1)
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#endif
+
+/*============================================================================
+ FXAA CONSOLE PS3 - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS
+ //
+ // Consoles the sharpness of edges on PS3 only.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 8.0 is sharper
+ // 4.0 is softer
+ // 2.0 is really soft (good for vector graphics inputs)
+ //
+ #if 1
+ #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 8.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 4.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 2.0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD
+ //
+ // Only effects PS3.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 0.25 and 0.125.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 0.125 leaves less aliasing, but is softer
+ // 0.25 leaves more aliasing, and is sharper
+ //
+ #if 1
+ #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.125
+ #else
+ #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.25
+ #endif
+#endif
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+------------------------------------------------------------------------------
+NOTE the other tuning knobs are now in the shader function inputs!
+============================================================================*/
+#ifndef FXAA_QUALITY_X_PRESET
+ //
+ // Choose the quality preset.
+ // This needs to be compiled into the shader as it effects code.
+ // Best option to include multiple presets is to
+ // in each shader define the preset, then include this file.
+ //
+ // OPTIONS
+ // -----------------------------------------------------------------------
+ // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
+ // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
+ // 39 - no dither, very expensive
+ //
+ // NOTES
+ // -----------------------------------------------------------------------
+ // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
+ // 13 = about same speed as FXAA 3.9 and better than 12
+ // 23 = closest to FXAA 3.9 visually and performance wise
+ // _ = the lowest digit is directly related to performance
+ // _ = the highest digit is directly related to style
+ //
+ #define FXAA_QUALITY_X_PRESET 12
+#endif
+
+
+/*============================================================================
+
+ FXAA QUALITY - PRESETS
+
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY_X_PRESET == 10)
+ #define FXAA_QUALITY_X_PS 3
+ #define FXAA_QUALITY_X_P0 1.5
+ #define FXAA_QUALITY_X_P1 3.0
+ #define FXAA_QUALITY_X_P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 11)
+ #define FXAA_QUALITY_X_PS 4
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 3.0
+ #define FXAA_QUALITY_X_P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 12)
+ #define FXAA_QUALITY_X_PS 5
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 4.0
+ #define FXAA_QUALITY_X_P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 13)
+ #define FXAA_QUALITY_X_PS 6
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 4.0
+ #define FXAA_QUALITY_X_P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 14)
+ #define FXAA_QUALITY_X_PS 7
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 4.0
+ #define FXAA_QUALITY_X_P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 15)
+ #define FXAA_QUALITY_X_PS 8
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 4.0
+ #define FXAA_QUALITY_X_P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY_X_PRESET == 20)
+ #define FXAA_QUALITY_X_PS 3
+ #define FXAA_QUALITY_X_P0 1.5
+ #define FXAA_QUALITY_X_P1 2.0
+ #define FXAA_QUALITY_X_P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 21)
+ #define FXAA_QUALITY_X_PS 4
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 22)
+ #define FXAA_QUALITY_X_PS 5
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 23)
+ #define FXAA_QUALITY_X_PS 6
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 24)
+ #define FXAA_QUALITY_X_PS 7
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 3.0
+ #define FXAA_QUALITY_X_P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 25)
+ #define FXAA_QUALITY_X_PS 8
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 4.0
+ #define FXAA_QUALITY_X_P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 26)
+ #define FXAA_QUALITY_X_PS 9
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 4.0
+ #define FXAA_QUALITY_X_P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 27)
+ #define FXAA_QUALITY_X_PS 10
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 4.0
+ #define FXAA_QUALITY_X_P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 28)
+ #define FXAA_QUALITY_X_PS 11
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 2.0
+ #define FXAA_QUALITY_X_P9 4.0
+ #define FXAA_QUALITY_X_P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY_X_PRESET == 29)
+ #define FXAA_QUALITY_X_PS 12
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.5
+ #define FXAA_QUALITY_X_P2 2.0
+ #define FXAA_QUALITY_X_P3 2.0
+ #define FXAA_QUALITY_X_P4 2.0
+ #define FXAA_QUALITY_X_P5 2.0
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 2.0
+ #define FXAA_QUALITY_X_P9 2.0
+ #define FXAA_QUALITY_X_P10 4.0
+ #define FXAA_QUALITY_X_P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY_X_PRESET == 39)
+ #define FXAA_QUALITY_X_PS 12
+ #define FXAA_QUALITY_X_P0 1.0
+ #define FXAA_QUALITY_X_P1 1.0
+ #define FXAA_QUALITY_X_P2 1.0
+ #define FXAA_QUALITY_X_P3 1.0
+ #define FXAA_QUALITY_X_P4 1.0
+ #define FXAA_QUALITY_X_P5 1.5
+ #define FXAA_QUALITY_X_P6 2.0
+ #define FXAA_QUALITY_X_P7 2.0
+ #define FXAA_QUALITY_X_P8 2.0
+ #define FXAA_QUALITY_X_P9 2.0
+ #define FXAA_QUALITY_X_P10 4.0
+ #define FXAA_QUALITY_X_P11 8.0
+#endif
+
+
+
+/*============================================================================
+
+ API PORTING
+
+============================================================================*/
+#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)
+ #define FxaaBool bool
+ #define FxaaDiscard discard
+ #define FxaaFloat float
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaHalf float
+ #define FxaaHalf2 vec2
+ #define FxaaHalf3 vec3
+ #define FxaaHalf4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaTex sampler2D
+#else
+ #define FxaaBool bool
+ #define FxaaDiscard clip(-1)
+ #define FxaaFloat float
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaHalf half
+ #define FxaaHalf2 half2
+ #define FxaaHalf3 half3
+ #define FxaaHalf4 half4
+ #define FxaaSat(x) saturate(x)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_120 == 1)
+ // Requires,
+ // #version 120
+ // And at least,
+ // #extension GL_EXT_gpu_shader4 : enable
+ // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
+ #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
+ #if (FXAA_FAST_PIXEL_OFFSET == 1)
+ #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
+ #else
+ #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
+ #endif
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_130 == 1)
+ // Requires "#version 130" or better
+ #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1)
+ #define FxaaInt2 float2
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
+ #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_4 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_5 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+ #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)
+ #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)
+ #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)
+ #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)
+#endif
+
+
+/*============================================================================
+ GREEN AS LUMA OPTION SUPPORT FUNCTION
+============================================================================*/
+#if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
+#else
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+#if (FXAA_PC == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+ //
+ // Used only for FXAA Console, and not used on the 360 version.
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy_X_} = upper left of pixel
+ // {_X_zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ // if (FXAA_GREEN_AS_LUMA == 0)
+ // {_X__a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 2nd sampler.
+ // This sampler needs to have an exponent bias of -1.
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 3nd sampler.
+ // This sampler needs to have an exponent bias of -2.
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ FxaaFloat2 fxaaQualityRcpFrame,
+ //
+ // Only used on FXAA Console.
+ // This must be from a constant/uniform.
+ // This effects sub-pixel AA quality and inversely sharpness.
+ // Where N ranges between,
+ // N = 0.50 (default)
+ // N = 0.33 (sharper)
+ // {x_X__} = -N/screenWidthInPixels
+ // {_y_X_} = -N/screenHeightInPixels
+ // {_X_z_} = N/screenWidthInPixels
+ // {_X__w} = N/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ //
+ // Only used on FXAA Console.
+ // Not used on 360, but used on PS3 and PC.
+ // This must be from a constant/uniform.
+ // {x_X__} = -2.0/screenWidthInPixels
+ // {_y_X_} = -2.0/screenHeightInPixels
+ // {_X_z_} = 2.0/screenWidthInPixels
+ // {_X__w} = 2.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ //
+ // Only used on FXAA Console.
+ // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.
+ // This must be from a constant/uniform.
+ // {x_X__} = 8.0/screenWidthInPixels
+ // {_y_X_} = 8.0/screenHeightInPixels
+ // {_X_z_} = -4.0/screenWidthInPixels
+ // {_X__w} = -4.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY_X_SUBPIX define.
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ FxaaFloat fxaaQualitySubpix,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ FxaaFloat fxaaQualityEdgeThreshold,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE_X_EDGE_SHARPNESS define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only three safe values here: 2 and 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // For all other platforms can be a non-power of two.
+ // 8.0 is sharper (default!!!)
+ // 4.0 is softer
+ // 2.0 is really soft (good only for vector graphics inputs)
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 1/4 and 1/8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // The console setting has a different mapping than the quality setting.
+ // Other platforms can use other values.
+ // 0.125 leaves less aliasing, but is softer (default!!!)
+ // 0.25 leaves more aliasing, and is sharper
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ // This does not apply to PS3,
+ // PS3 was simplified to avoid more shader instructions.
+ // 0.06 - faster but more aliasing in darks
+ // 0.05 - default
+ // 0.04 - slower and less aliasing in darks
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ //
+ // Extra constants for 360 FXAA Console only.
+ // Use zeros or anything else for other platforms.
+ // These must be in physical constant registers and NOT immedates.
+ // Immedates will result in compiler un-optimizing.
+ // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ #if (FXAA_GATHER4_ALPHA == 1)
+ #if (FXAA_DISCARD == 0)
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ #endif
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
+ #else
+ FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
+ #endif
+ #if (FXAA_DISCARD == 1)
+ #define lumaM luma4A.w
+ #endif
+ #define lumaE luma4A.z
+ #define lumaS luma4A.x
+ #define lumaSE luma4A.y
+ #define lumaNW luma4B.w
+ #define lumaN luma4B.z
+ #define lumaW luma4B.x
+ #else
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat maxSM = max(lumaS, lumaM);
+ FxaaFloat minSM = min(lumaS, lumaM);
+ FxaaFloat maxESM = max(lumaE, maxSM);
+ FxaaFloat minESM = min(lumaE, minSM);
+ FxaaFloat maxWN = max(lumaN, lumaW);
+ FxaaFloat minWN = min(lumaN, lumaW);
+ FxaaFloat rangeMax = max(maxWN, maxESM);
+ FxaaFloat rangeMin = min(minWN, minESM);
+ FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ FxaaFloat range = rangeMax - rangeMin;
+ FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ FxaaBool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit)
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 0)
+ FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #else
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNS = lumaN + lumaS;
+ FxaaFloat lumaWE = lumaW + lumaE;
+ FxaaFloat subpixRcpRange = 1.0/range;
+ FxaaFloat subpixNSWE = lumaNS + lumaWE;
+ FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNESE = lumaNE + lumaSE;
+ FxaaFloat lumaNWNE = lumaNW + lumaNE;
+ FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNWSW = lumaNW + lumaSW;
+ FxaaFloat lumaSWSE = lumaSW + lumaSE;
+ FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
+ FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
+ FxaaBool horzSpan = edgeHorz >= edgeVert;
+ FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat gradientN = lumaN - lumaM;
+ FxaaFloat gradientS = lumaS - lumaM;
+ FxaaFloat lumaNN = lumaN + lumaM;
+ FxaaFloat lumaSS = lumaS + lumaM;
+ FxaaBool pairN = abs(gradientN) >= abs(gradientS);
+ FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ FxaaFloat2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY_X_P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY_X_P0;
+ FxaaFloat2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY_X_P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY_X_P0;
+ FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
+ FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ FxaaFloat subpixE = subpixC * subpixC;
+ FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ FxaaFloat gradientScaled = gradient * 1.0/4.0;
+ FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
+ FxaaFloat subpixF = subpixD * subpixE;
+ FxaaBool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
+ FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P1;
+ FxaaBool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY_X_PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dstN = posM.x - posN.x;
+ FxaaFloat dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ FxaaFloat spanLength = (dstP + dstN);
+ FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ FxaaFloat spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ FxaaBool directionN = dstN < dstP;
+ FxaaFloat dst = min(dstN, dstP);
+ FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
+ FxaaFloat subpixG = subpixF * subpixF;
+ FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ #if (FXAA_DISCARD == 1)
+ return FxaaTexTop(tex, posM);
+ #else
+ return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
+ #endif
+}
+/*==========================================================================*/
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - PC VERSION
+
+------------------------------------------------------------------------------
+Instead of using this on PC, I'd suggest just using FXAA Quality with
+ #define FXAA_QUALITY_X_PRESET 10
+Or
+ #define FXAA_QUALITY_X_PRESET 20
+Either are higher qualilty and almost as fast as this on modern PC GPUs.
+============================================================================*/
+#if (FXAA_PC_CONSOLE == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));
+ FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));
+ FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));
+ FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat lumaM = rgbyM.w;
+ #else
+ FxaaFloat lumaM = rgbyM.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);
+ lumaNe += 1.0/384.0;
+ FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);
+ FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
+ FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMinM = min(lumaMin, lumaM);
+ FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);
+ FxaaFloat lumaMaxM = max(lumaMax, lumaM);
+ FxaaFloat dirSwMinusNe = lumaSw - lumaNe;
+ FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;
+ FxaaFloat dirSeMinusNw = lumaSe - lumaNw;
+ if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir;
+ dir.x = dirSwMinusNe + dirSeMinusNw;
+ dir.y = dirSwMinusNe - dirSeMinusNw;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir1 = normalize(dir.xy);
+ FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);
+ FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;
+ FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);
+ FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;
+ FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
+ #else
+ FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);
+ #endif
+ if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;
+ return rgbyB; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - 360 PIXEL SHADER
+
+------------------------------------------------------------------------------
+This optimized version thanks to suggestions from Andy Luedke.
+Should be fully tex bound in all cases.
+As of the FXAA 3.11 release, I have still not tested this code,
+however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10.
+And note this is replacing the old unoptimized version.
+If it does not work, please let me know so I can fix it.
+============================================================================*/
+#if (FXAA_360 == 1)
+/*--------------------------------------------------------------------------*/
+ [reduceTempRegUsage(4)]
+float4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ float4 lumaNwNeSwSe;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ asm {
+ tfetch2D lumaNwNeSwSe.w_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._w_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X_w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X__w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #else
+ asm {
+ tfetch2D lumaNwNeSwSe.y_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._y_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X_y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._X__y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #endif
+/*--------------------------------------------------------------------------*/
+ lumaNwNeSwSe.y += 1.0/384.0;
+ float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);
+ float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);
+/*--------------------------------------------------------------------------*/
+ float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ float lumaMinM = min(lumaMin, rgbyM.w);
+ float lumaMaxM = max(lumaMax, rgbyM.w);
+ #else
+ float lumaMinM = min(lumaMin, rgbyM.y);
+ float lumaMaxM = max(lumaMax, rgbyM.y);
+ #endif
+ if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ float2 dir;
+ dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx);
+ dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy);
+ dir = normalize(dir);
+/*--------------------------------------------------------------------------*/
+ float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw;
+/*--------------------------------------------------------------------------*/
+ float4 dir2;
+ float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness;
+ dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5);
+ dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0));
+ float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0));
+ float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0));
+ float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+ float4 rgbyA = rgbyN1 + rgbyP1;
+ float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB;
+ rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA;
+ return rgbyR; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)
+
+==============================================================================
+The code below does not exactly match the assembly.
+I have a feeling that 12 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h0.w(TRUE), v5.xwxx, #0
+ 6: addh h0.z(TRUE), -h2, h0.w
+ 7: texpkb h1.w(TRUE), v5, #0
+ 9: addh h0.x(TRUE), h0.z, -h1.w
+ 10: addh h3.w(TRUE), h0.z, h1
+ 11: texpkb h2.w(TRUE), v5.zwzz, #0
+ 13: addh h0.z(TRUE), h3.w, -h2.w
+ 14: addh h0.x(TRUE), h2.w, h0
+ 15: nrmh h1.xz(TRUE), h0_n
+ 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|
+ 17: maxh h4.w(TRUE), h0, h1
+ 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n
+ 19: movr r1.zw(TRUE), v4.xxxy
+ 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww
+ 22: minh h5.w(TRUE), h0, h1
+ 23: texpkb h0(TRUE), r2.xzxx, #0
+ 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1
+ 27: maxh h4.x(TRUE), h2.z, h2.w
+ 28: texpkb h1(TRUE), r0.zwzz, #0
+ 30: addh_d2 h1(TRUE), h0, h1
+ 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 33: texpkb h0(TRUE), r0, #0
+ 35: minh h4.z(TRUE), h2, h2.w
+ 36: fenct TRUE
+ 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 39: texpkb h2(TRUE), r1, #0
+ 41: addh_d2 h0(TRUE), h0, h2
+ 42: maxh h2.w(TRUE), h4, h4.x
+ 43: minh h2.x(TRUE), h5.w, h4.z
+ 44: addh_d2 h0(TRUE), h0, h1
+ 45: slth h2.x(TRUE), h0.w, h2
+ 46: sgth h2.w(TRUE), h0, h2
+ 47: movh h0(TRUE), h0
+ 48: addx.c0 rc(TRUE), h2, h2.w
+ 49: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---;
+ | SCB1 | add | 10: ADDh h3.w, h0.---z, h1;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h2.w---, h0;
+ | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-;
+ | | |
+ 5 | SCT1 | mov | 15: NRMh h1.xz, h0;
+ | SRB | nrm | 15: NRMh h1.xz, h0;
+ | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|;
+ | SCB1 | max | 17: MAXh h4.w, h0, h1;
+ | | |
+ 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0;
+ | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy;
+ | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-;
+ | SCB1 | min | 22: MINh h5.w, h0, h1;
+ | | |
+ 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---;
+ | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1;
+ | | |
+ 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | SCB0/1 | add | 30: ADDh/2 h1, h0, h1;
+ | | |
+ 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB1 | min | 35: MINh h4.z, h2, h2.--w-;
+ | | |
+ 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | SCB0/1 | add | 41: ADDh/2 h0, h0, h2;
+ | | |
+ 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---;
+ | SCT1 | max | 42: MAXh h2.w, h4, h4.---x;
+ | SCB0/1 | add | 44: ADDh/2 h0, h0, h1;
+ | | |
+ 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2;
+ | SCT1 | set | 46: SGTh h2.w, h0, h2;
+ | SCB0/1 | mul | 47: MOVh h0, h0;
+ | | |
+ 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---;
+ | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 0% 0% 50%
+ 6: 100% 0% 75%
+ 7: 0% 100% 75%
+ 8: 0% 100% 100%
+ 9: 0% 100% 25%
+ 10: 0% 100% 100%
+ 11: 50% 0% 100%
+ 12: 50% 0% 100%
+ 13: 25% 0% 100%
+
+MEAN: 17% 61% 67%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 0% 100%
+ 2: 0% 0% 100% 0% 100%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 0% 0% 0% 100% 100%
+ 6: 100% 100% 0% 100% 100%
+ 7: 0% 0% 100% 100% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 0% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 100% 100% 0% 100% 100%
+ 12: 100% 100% 0% 100% 100%
+ 13: 100% 0% 0% 100% 100%
+
+MEAN: 30% 23% 61% 76% 100%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 13 cycles, 3 r regs, 923,076,923 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O3
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 dir;
+ half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ lumaNe.w += half(1.0/512.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+ #else
+ lumaNe.y += half(1.0/512.0);
+ dir.x = -lumaNe.y;
+ dir.z = -lumaNe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+ #else
+ dir.x += lumaSw.y;
+ dir.z += lumaSw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+ #else
+ dir.x -= lumaNw.y;
+ dir.z += lumaNw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+ #else
+ dir.x += lumaSe.y;
+ dir.z -= lumaSe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (7)
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (8)
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (11)
+ // compilier moves these scalar ops up to other cycles
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ #else
+ half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y));
+ half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y));
+ #endif
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (12)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (13)
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)
+
+==============================================================================
+The code mostly matches the assembly.
+I have a feeling that 14 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks).
+Will look at fixing this for FXAA 3.12.
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h1.w(TRUE), v5.xwxx, #0
+ 6: addh h0.x(TRUE), h1.w, -h2.y
+ 7: texpkb h2.w(TRUE), v5.zwzz, #0
+ 9: minh h4.w(TRUE), h2.y, h2
+ 10: maxh h5.x(TRUE), h2.y, h2.w
+ 11: texpkb h0.w(TRUE), v5, #0
+ 13: addh h3.w(TRUE), -h0, h0.x
+ 14: addh h0.x(TRUE), h0.w, h0
+ 15: addh h0.z(TRUE), -h2.w, h0.x
+ 16: addh h0.x(TRUE), h2.w, h3.w
+ 17: minh h5.y(TRUE), h0.w, h1.w
+ 18: nrmh h2.xz(TRUE), h0_n
+ 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|
+ 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w
+ 21: movr r1.zw(TRUE), v4.xxxy
+ 22: maxh h2.w(TRUE), h0, h1
+ 23: fenct TRUE
+ 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 26: texpkb h0(TRUE), r0, #0
+ 28: maxh h5.x(TRUE), h2.w, h5
+ 29: minh h5.w(TRUE), h5.y, h4
+ 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 32: texpkb h2(TRUE), r1, #0
+ 34: addh_d2 h2(TRUE), h0, h2
+ 35: texpkb h1(TRUE), v4, #0
+ 37: maxh h5.y(TRUE), h5.x, h1.w
+ 38: minh h4.w(TRUE), h1, h5
+ 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 41: texpkb h0(TRUE), r0, #0
+ 43: addh_m8 h5.z(TRUE), h5.y, -h4.w
+ 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 46: texpkb h3(TRUE), r2, #0
+ 48: addh_d2 h0(TRUE), h0, h3
+ 49: addh_d2 h3(TRUE), h0, h2
+ 50: movh h0(TRUE), h3
+ 51: slth h3.x(TRUE), h3.w, h5.w
+ 52: sgth h3.w(TRUE), h3, h5.x
+ 53: addx.c0 rc(TRUE), h3.x, h3
+ 54: slth.c0 rc(TRUE), h5.z, h5
+ 55: movh h0(c0.NE.w), h2
+ 56: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---;
+ | SCB1 | min | 9: MINh h4.w, h2.---y, h2;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h0.w---, h0;
+ | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x;
+ | | |
+ 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---;
+ | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-;
+ | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--;
+ | | |
+ 6 | SCT1 | mov | 18: NRMh h2.xz, h0;
+ | SRB | nrm | 18: NRMh h2.xz, h0;
+ | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|;
+ | | |
+ 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--;
+ | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy;
+ | SCB1 | max | 22: MAXh h2.w, h0, h1;
+ | | |
+ 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | SCB0 | max | 28: MAXh h5.x, h2.w---, h5;
+ | SCB1 | min | 29: MINh h5.w, h5.---y, h4;
+ | | |
+ 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | SCB0/1 | add | 34: ADDh/2 h2, h0, h2;
+ | | |
+ 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--;
+ | SCB1 | min | 38: MINh h4.w, h1, h5;
+ | | |
+ 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--;
+ | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--;
+ | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-;
+ | | |
+ 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | SCB0/1 | add | 48: ADDh/2 h0, h0, h3;
+ | | |
+ 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2;
+ | SCB0/1 | mul | 50: MOVh h0, h3;
+ | | |
+ 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---;
+ | SCT1 | set | 52: SGTh h3.w, h3, h5.---x;
+ | SCB0 | set | 54: SLThc0 rc, h5.z---, h5;
+ | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3;
+ | | |
+ 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2;
+ | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 50% 0% 25%
+ 6: 0% 0% 25%
+ 7: 100% 0% 25%
+ 8: 0% 100% 50%
+ 9: 0% 100% 100%
+ 10: 0% 100% 50%
+ 11: 0% 100% 75%
+ 12: 0% 100% 100%
+ 13: 100% 0% 100%
+ 14: 50% 0% 50%
+ 15: 100% 0% 100%
+
+MEAN: 26% 60% 56%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 100% 0%
+ 2: 0% 0% 100% 100% 0%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 100% 100% 0% 100% 0%
+ 6: 0% 0% 0% 0% 100%
+ 7: 100% 100% 0% 0% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 100% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 0% 0% 100% 100% 100%
+ 12: 0% 0% 100% 100% 100%
+ 13: 100% 100% 0% 100% 100%
+ 14: 100% 100% 0% 100% 100%
+ 15: 100% 100% 0% 100% 100%
+
+MEAN: 33% 33% 60% 86% 80%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 15 cycles, 3 r regs, 800,000,000 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O2
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaNe = rgbyNe.w + half(1.0/512.0);
+ #else
+ half lumaNe = rgbyNe.y + half(1.0/512.0);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaSwNegNe = lumaSw.w - lumaNe;
+ #else
+ half lumaSwNegNe = lumaSw.y - lumaNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);
+ half lumaMinNwSw = min(lumaNw.w, lumaSw.w);
+ #else
+ half lumaMaxNwSw = max(lumaNw.y, lumaSw.y);
+ half lumaMinNwSw = min(lumaNw.y, lumaSw.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half dirZ = lumaNw.w + lumaSwNegNe;
+ half dirX = -lumaNw.w + lumaSwNegNe;
+ #else
+ half dirZ = lumaNw.y + lumaSwNegNe;
+ half dirX = -lumaNw.y + lumaSwNegNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half3 dir;
+ dir.y = 0.0;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x = lumaSe.w + dirX;
+ dir.z = -lumaSe.w + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.w);
+ #else
+ dir.x = lumaSe.y + dirX;
+ dir.z = -lumaSe.y + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir).xz;
+ half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (7)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNeSe = max(lumaNe, lumaSe.w);
+ #else
+ half lumaMaxNeSe = max(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (8)
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);
+ half lumaMin = min(lumaMinNwSw, lumaMinNeSe);
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ #else
+ half lumaMaxM = max(lumaMax, rgbyM.y);
+ half lumaMinM = min(lumaMin, rgbyM.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (11)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+// (12)
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (13)
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (14)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+ bool earlyExit = lumaRangeM < lumaMax;
+ bool twoTap = twoTapLt || twoTapGt;
+/*--------------------------------------------------------------------------*/
+// (15)
+ if(twoTap) rgby2 = rgby1;
+ if(earlyExit) rgby2 = rgbyM;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+#else
+#define FXAA_SPAN_MAX 8.0
+#define FXAA_REDUCE_MUL 1.0/8.0
+#define FXAA_REDUCE_MIN 1.0/128.0
+
+vec4 FxaaPixelShader(
+ vec2 pos,
+ vec4 fxaaConsolePosPos,
+ sampler2D tex,
+ sampler2D fxaaConsole360TexExpBiasNegOne,
+ sampler2D fxaaConsole360TexExpBiasNegTwo,
+ vec2 fxaaQualityRcpFrame,
+ vec4 fxaaConsoleRcpFrameOpt,
+ vec4 fxaaConsoleRcpFrameOpt2,
+ vec4 fxaaConsole360RcpFrameOpt2,
+ float fxaaQualitySubpix,
+ float fxaaQualityEdgeThreshold,
+ float fxaaQualityEdgeThresholdMin,
+ float fxaaConsoleEdgeSharpness,
+ float fxaaConsoleEdgeThreshold,
+ float fxaaConsoleEdgeThresholdMin,
+ vec4 fxaaConsole360ConstDir
+) {
+#define Tex() qf_texture(tex, pos).rgb
+#define TexOfs(ofs) qf_texture(tex, pos + ofs).rgb
+#define TexOfsInv(ofs) qf_texture(tex, pos + ofs * fxaaQualityRcpFrame).rgb
+
+ vec3 rgbNW = TexOfsInv(vec2(-1.0,-1.0));
+ vec3 rgbNE = TexOfsInv(vec2(1.0,-1.0));
+ vec3 rgbSW = TexOfsInv(vec2(-1.0,1.0));
+ vec3 rgbSE = TexOfsInv(vec2(1.0,1.0));
+ vec3 rgbM = Tex();
+
+ vec3 luma = vec3(0.299, 0.587, 0.114);
+ float lumaNW = dot(rgbNW, luma);
+ float lumaNE = dot(rgbNE, luma);
+ float lumaSW = dot(rgbSW, luma);
+ float lumaSE = dot(rgbSE, luma);
+ float lumaM = dot(rgbM, luma);
+
+ float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+ float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+ vec2 dir;
+ dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+ dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+ float dirReduce = max(
+ (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
+ FXAA_REDUCE_MIN);
+ float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
+
+ dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
+ max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
+ dir * rcpDirMin)) * fxaaQualityRcpFrame;
+
+ vec3 rgbA = (1.0/2.0) * (
+ TexOfs(dir * (1.0/3.0 - 0.5)) +
+ TexOfs(dir * (2.0/3.0 - 0.5)));
+ vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
+ TexOfs(dir * (0.0/3.0 - 0.5)) +
+ TexOfs(dir * (3.0/3.0 - 0.5)));
+ float lumaB = dot(rgbB, luma);
+
+ if((lumaB < lumaMin) || (lumaB > lumaMax)){
+ return vec4(rgbA, 1.0);
+ }else{
+ return vec4(rgbB, 1.0);
+ }
+}
+
+
+#endif
void main(void)
{
+ // Only used on FXAA Quality.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ float QualitySubpix = 0.75;
-myhalf4 color;
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.033 - very high quality (slower)
+ float QualityEdgeThreshold = 0.166;
+ float QualityEdgeThresholdMin = 0.0;
-color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord));
+ vec4 ConsolePosPos = vec4(0.0,0.0,0.0,0.0);
+ vec4 ConsoleRcpFrameOpt = vec4(0.0,0.0,0.0,0.0);
+ vec4 ConsoleRcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0);
+ vec4 Console360RcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0);
+ float ConsoleEdgeSharpness = 8.0;
+ float ConsoleEdgeThreshold = 0.125;
+ float ConsoleEdgeThresholdMin = 0.05;
+ vec4 Console360ConstDir = vec4(1.0, -1.0, 0.25, -0.25);
-gl_FragColor = vec4(color);
+ qf_FragColor = FxaaPixelShader(v_TexCoord, ConsolePosPos, u_BaseTexture, u_BaseTexture, u_BaseTexture,
+ u_TextureParams.zw, ConsoleRcpFrameOpt, ConsoleRcpFrameOpt2, Console360RcpFrameOpt2,
+ QualitySubpix, QualityEdgeThreshold, QualityEdgeThresholdMin, ConsoleEdgeSharpness,
+ ConsoleEdgeThreshold, ConsoleEdgeThresholdMin, Console360ConstDir);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/250.shader_test b/shaders/warsow/250.shader_test
new file mode 100644
index 0000000..e9cc9e1
--- /dev/null
+++ b/shaders/warsow/250.shader_test
@@ -0,0 +1,1675 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/253.shader_test b/shaders/warsow/253.shader_test
new file mode 100644
index 0000000..dd16193
--- /dev/null
+++ b/shaders/warsow/253.shader_test
@@ -0,0 +1,1698 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 2
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+t = sin(TexCoord.s * 4.000000 + u_QF_ShaderTime * -1.500000);
+Position.xyz += max (-1.0 + 1.000000, t) * 7.000000 * Normal.xyz;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_PCF
+#define NUM_SHADOWS 2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/256.shader_test b/shaders/warsow/256.shader_test
new file mode 100644
index 0000000..885e14f
--- /dev/null
+++ b/shaders/warsow/256.shader_test
@@ -0,0 +1,1677 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_PCF
+#define NUM_SHADOWS 2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_PCF
+#define NUM_SHADOWS 2
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/259.shader_test b/shaders/warsow/259.shader_test
new file mode 100644
index 0000000..0ec59aa
--- /dev/null
+++ b/shaders/warsow/259.shader_test
@@ -0,0 +1,1675 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_PCF
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
+
+
+#ifndef NUM_SHADOWS
+#define NUM_SHADOWS 1
+#endif
+
+qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS];
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS];
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ for (int i = 0; i < NUM_SHADOWS; i++)
+ {
+ v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position;
+ // a trick whish allows us not to perform the
+ // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)'
+ // computation in the fragment shader
+ v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5;
+ }
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_RGB_SHADOW
+uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy)))
+#else
+uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS];
+# define dshadow2D(t,v) float(qf_shadow(t,v))
+#endif
+
+uniform float u_ShadowAlpha;
+uniform float u_ShadowProjDistance[NUM_SHADOWS];
+uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS];
+
+void main(void)
+{
+ float finalcolor = 1.0;
+
+#if NUM_SHADOWS >= 1
+#define SHADOW_INDEX 0
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 2
+#define SHADOW_INDEX 1
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 3
+#define SHADOW_INDEX 2
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+#if NUM_SHADOWS >= 4
+#define SHADOW_INDEX 3
+ {
+ vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w);
+
+ // this keeps shadows from appearing on surfaces behind frustum's nearplane
+ float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0);
+
+ //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5);
+ shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width
+ shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0);
+ shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y));
+
+ vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw;
+
+ float f;
+
+ #ifdef APPLY_DITHER
+
+ # ifdef APPLY_PCF
+ # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z))
+
+ // this method can be described as a 'dithered pinwheel' (4 texture lookups)
+ // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF,
+ // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+
+ vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0);
+ offset_dither.y += offset_dither.x; // y ^= x in floating point
+ offset_dither.y *= step(offset_dither.y, 1.1);
+
+ vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale;
+ float group1 = texval(-0.4, 1.0);
+ float group2 = texval(-1.0, -0.4);
+ float group3 = texval( 0.4, -1.0);
+ float group4 = texval( 1.0, 0.4);
+
+ f = dot(vec4(0.25), vec4(group1, group2, group3, group4));
+ # else
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));
+ # endif // APPLY_PCF
+
+ #else
+ // an essay by eihrul:
+ // now think of bilinear filtering as a 1x1 weighted box filter
+ // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on
+ // with a linear shadowmap filter, you are getting that, like normal bilinear sampling
+ // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing
+ // the bilinear filtering on that
+ // so now if you consider your 2x2 filter you have
+ // each of those taps is actually using linear filtering as you've configured it
+ // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2
+ // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels
+ // and running a 3x3 weighted box filter on it
+ // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each
+ // tap, rather than the filtered result
+ // which is what the ARB_texture_gather extension is for
+ // NOTE: we're using emulation of texture_gather now
+
+ # ifdef APPLY_PCF
+ # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z))
+
+ vec2 offset = fract(shadowmaptc.xy - 0.5);
+ vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy;
+ f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));
+
+ #else
+
+ f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z));
+
+ #endif // APPLY_PCF
+
+ #endif // APPLY_DITHER
+
+ finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0);
+ }
+
+#undef SHADOW_INDEX
+#endif
+
+ qf_FragColor = vec4(vec3(finalcolor),1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+
diff --git a/shaders/warsow/262.shader_test b/shaders/warsow/262.shader_test
new file mode 100644
index 0000000..52d7113
--- /dev/null
+++ b/shaders/warsow/262.shader_test
@@ -0,0 +1,1795 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+#define APPLY_SOFT_PARTICLE
+#define APPLY_DEFORMVERTS
+
+#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpritePoint;
+#else
+#define a_SpritePoint vec4(0.0)
+#endif
+
+#if defined(APPLY_AUTOSPRITE2)
+attribute vec4 a_SpriteRightUpAxis;
+#else
+#define a_SpriteRightUpAxis vec4(0.0)
+#endif
+
+void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+float t = 0.0;
+vec3 dist;
+vec3 right, up, forward, newright;
+
+#if defined(WAVE_SIN)
+// local sprite axes
+right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide;
+up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw);
+
+// mid of quad to camera vector
+dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz;
+
+// filter any longest-axis-parts off the camera-direction
+forward = normalize(dist - up * dot(dist, up));
+
+// the right axis vector as it should be to face the camera
+newright = cross(up, forward);
+
+// rotate the quad vertex around the up axis vector
+t = dot(right, Position.xyz - a_SpritePoint.xyz);
+Position.xyz += t * (newright - right);
+Normal.xyz = forward;
+#endif
+}
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_AUTOSPRITE2
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/28.shader_test b/shaders/warsow/28.shader_test
new file mode 100644
index 0000000..7031a6f
--- /dev/null
+++ b/shaders/warsow/28.shader_test
@@ -0,0 +1,1031 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+myhalf3 YUV2RGB(vec3 yuv)
+{
+ // Standard definition TV color matrix
+ const mat3 yuv2rgb = mat3(
+ 1.0, 1.0, 1.0,
+ 0.0, -0.343, -0.711,
+ 1.400, -0.711, 0.0
+ );
+ const vec3 yuv_sub = vec3(
+ 0.0, 0.5, 0.5
+ );
+
+ return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 );
+}
+
+myhalf3 YUV2RGB_HDTV(vec3 yuv)
+{
+ // High Definition TV color matrix
+ const mat3 yuv2rgb = mat3(
+ 1.164, 1.164, 1.164,
+ 0.0, -0.213, 2.212,
+ 1.793, -0.533, 0.0
+ );
+ const vec3 yuv_sub = vec3(
+ 0.0625, 0.5, 0.5
+ );
+
+ return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 );
+}
+
+
+qf_varying vec2 v_TexCoord;
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+void main(void)
+{
+ gl_Position = u_ModelViewProjectionMatrix * a_Position;
+ v_TexCoord = a_TexCoord;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_YUVTextureY;
+uniform sampler2D u_YUVTextureU;
+uniform sampler2D u_YUVTextureV;
+
+void main(void)
+{
+ qf_FragColor = vec4(YUV2RGB_HDTV(vec3(
+ qf_texture(u_YUVTextureY, v_TexCoord).r,
+ qf_texture(u_YUVTextureU, v_TexCoord).r,
+ qf_texture(u_YUVTextureV, v_TexCoord).r
+ )), 1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+myhalf3 YUV2RGB(vec3 yuv)
+{
+ // Standard definition TV color matrix
+ const mat3 yuv2rgb = mat3(
+ 1.0, 1.0, 1.0,
+ 0.0, -0.343, -0.711,
+ 1.400, -0.711, 0.0
+ );
+ const vec3 yuv_sub = vec3(
+ 0.0, 0.5, 0.5
+ );
+
+ return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 );
+}
+
+myhalf3 YUV2RGB_HDTV(vec3 yuv)
+{
+ // High Definition TV color matrix
+ const mat3 yuv2rgb = mat3(
+ 1.164, 1.164, 1.164,
+ 0.0, -0.213, 2.212,
+ 1.793, -0.533, 0.0
+ );
+ const vec3 yuv_sub = vec3(
+ 0.0625, 0.5, 0.5
+ );
+
+ return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 );
+}
+
+
+qf_varying vec2 v_TexCoord;
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+
+void main(void)
+{
+ gl_Position = u_ModelViewProjectionMatrix * a_Position;
+ v_TexCoord = a_TexCoord;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform sampler2D u_YUVTextureY;
+uniform sampler2D u_YUVTextureU;
+uniform sampler2D u_YUVTextureV;
+
+void main(void)
+{
+ qf_FragColor = vec4(YUV2RGB_HDTV(vec3(
+ qf_texture(u_YUVTextureY, v_TexCoord).r,
+ qf_texture(u_YUVTextureU, v_TexCoord).r,
+ qf_texture(u_YUVTextureV, v_TexCoord).r
+ )), 1.0);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/30.shader_test b/shaders/warsow/30.shader_test
deleted file mode 100644
index 04dc676..0000000
--- a/shaders/warsow/30.shader_test
+++ /dev/null
@@ -1,26 +0,0 @@
-[require]
-GLSL >= 1.10
-
-[fragment shader]
-#version 130
-uniform sampler2D texSampler;
-in vec3 texCoords;
-out vec4 out_color;
-
-void main()
-{
- out_color = texture(texSampler, texCoords.xy);
-}
-
-[vertex shader]
-#version 130
-in vec2 position;
-in vec3 textureCoords;
-out vec3 texCoords;
-void main()
-{
- texCoords = textureCoords;
- gl_Position = vec4(position, 0.0, 1.0);
-}
-
-
diff --git a/shaders/warsow/31.shader_test b/shaders/warsow/31.shader_test
index f005219..ce51847 100644
--- a/shaders/warsow/31.shader_test
+++ b/shaders/warsow/31.shader_test
@@ -1,138 +1,767 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -140,342 +769,1023 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-gl_FragColor = vec4(color);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
}
-#endif // FRAGMENT_SHADER
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+#define NUM_BONE_INFLUENCES 1
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#endif
+#endif
-#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-uniform vec3 EyeOrigin;
+uniform Fog u_Fog;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -483,207 +1793,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
-#ifdef APPLY_LIGHTSTYLE0
+ // deluxemapping using light vectors in modelspace
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/34.shader_test b/shaders/warsow/34.shader_test
index 62d5d00..fb99ed9 100644
--- a/shaders/warsow/34.shader_test
+++ b/shaders/warsow/34.shader_test
@@ -1,140 +1,770 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
#endif
+
#endif
#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -142,344 +772,1026 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-gl_FragColor = vec4(color);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // FRAGMENT_SHADER
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
#define APPLY_FBLIGHTMAP
-// Warsow GLSL shader
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#endif
+#endif
-#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-uniform vec3 EyeOrigin;
+uniform Fog u_Fog;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -487,207 +1799,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/37.shader_test b/shaders/warsow/37.shader_test
index 6e68fc9..04545c1 100644
--- a/shaders/warsow/37.shader_test
+++ b/shaders/warsow/37.shader_test
@@ -1,141 +1,771 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -143,345 +773,1027 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
-#ifdef APPLY_LIGHTSTYLE0
+ // deluxemapping using light vectors in modelspace
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
#else
-gl_FragColor = vec4(color);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // FRAGMENT_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
#define APPLY_FBLIGHTMAP
#define APPLY_SPECULAR
-// Warsow GLSL shader
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#endif
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-#ifdef VERTEX_SHADER
-// Vertex shader
+uniform Fog u_Fog;
-uniform vec3 EyeOrigin;
+#define FOG_TEXCOORD_STEP 1.0/256.0
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -489,207 +1801,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/4.shader_test b/shaders/warsow/4.shader_test
index 62d5d00..9fdefaf 100644
--- a/shaders/warsow/4.shader_test
+++ b/shaders/warsow/4.shader_test
@@ -1,693 +1,1271 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-void main()
+if (numWeights > 2)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-#endif
-#endif
+}
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform ivec4 u_Viewport; // x, y, width, height
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+myhalf3 Greyscale(myhalf3 color)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
}
+
+
+qf_varying vec4 v_TexCoord;
+qf_varying vec4 v_ProjVector;
+#ifdef APPLY_EYEDOT
+qf_varying vec3 v_EyeVector;
#endif
-void main()
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+#ifdef APPLY_EYEDOT
+uniform float u_FrontPlane;
#endif
-// deluxemapping using light vectors in modelspace
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+ myhalf4 inColor = myhalf4(a_Color);
-#ifdef APPLY_LIGHTSTYLE0
+ TransformVerts(Position, Normal, TexCoord);
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor));
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+ v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
-#define NORMALIZE_DIFFUSE_NORMAL
+ vec2 textureMatrix3_[3];
+ textureMatrix3_[0] = u_TextureMatrix[0];
+ textureMatrix3_[1] = u_TextureMatrix[1];
+ textureMatrix3_[2] = -u_TextureMatrix[2];
+ v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord);
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+#ifdef APPLY_EYEDOT
+ mat3 v_StrMatrix;
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+ v_ProjVector = gl_Position;
+}
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#endif // VERTEX_SHADER
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+#ifdef APPLY_DUDV
+uniform sampler2D u_DuDvMapTexture;
#endif
+
+#ifdef APPLY_EYEDOT
+uniform sampler2D u_NormalmapTexture;
#endif
-#endif
-#endif
+uniform sampler2D u_ReflectionTexture;
+uniform sampler2D u_RefractionTexture;
+
+void main(void)
+{
+ myhalf3 color;
-#ifdef APPLY_SPECULAR
+#ifdef APPLY_DUDV
+ vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25)));
+ vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2);
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ vec3 fdist = vec3(0.0);
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ // get projective texcoords
+ float scale = float(1.0 / float(v_ProjVector.w));
+ float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width
+ float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height
+ vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
+ projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
+ projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ myhalf3 refr = myhalf3(0.0);
+ myhalf3 refl = myhalf3(0.0);
+
+#ifdef APPLY_EYEDOT
+ // calculate dot product between the surface normal and eye vector
+ // great for simulating qf_varying water translucency based on the view angle
+ myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5));
+ vec3 eyeNormal = normalize(myhalf3(v_EyeVector));
+
+ float refrdot = float(dot(surfaceNormal, eyeNormal));
+ //refrdot = float (clamp (refrdot, 0.0, 1.0));
+ float refldot = 1.0 - refrdot;
+ // get refraction and reflection
+
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot;
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
+
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord)));
#endif
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord)));
+#endif
+
+#endif // APPLY_EYEDOT
+
+ // add reflection and refraction
+#ifdef APPLY_DISTORTION_ALPHA
+ color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a)));
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf3(qf_FrontColor.rgb) + refr + refl;
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#ifdef APPLY_GREYSCALE
+ qf_FragColor = vec4(vec3(Greyscale(color)),1.0);
#else
-gl_FragColor = vec4(color);
+ qf_FragColor = vec4(vec3(color),1.0);
#endif
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-#endif
-#endif
+}
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform ivec4 u_Viewport; // x, y, width, height
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+myhalf3 Greyscale(myhalf3 color)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
}
+
+
+qf_varying vec4 v_TexCoord;
+qf_varying vec4 v_ProjVector;
+#ifdef APPLY_EYEDOT
+qf_varying vec3 v_EyeVector;
#endif
-void main()
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+#ifdef APPLY_EYEDOT
+uniform float u_FrontPlane;
#endif
-// deluxemapping using light vectors in modelspace
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+ myhalf4 inColor = myhalf4(a_Color);
-#ifdef APPLY_LIGHTSTYLE0
+ TransformVerts(Position, Normal, TexCoord);
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor));
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+ v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
-#define NORMALIZE_DIFFUSE_NORMAL
+ vec2 textureMatrix3_[3];
+ textureMatrix3_[0] = u_TextureMatrix[0];
+ textureMatrix3_[1] = u_TextureMatrix[1];
+ textureMatrix3_[2] = -u_TextureMatrix[2];
+ v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord);
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+#ifdef APPLY_EYEDOT
+ mat3 v_StrMatrix;
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+ v_ProjVector = gl_Position;
+}
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#endif // VERTEX_SHADER
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+#ifdef APPLY_DUDV
+uniform sampler2D u_DuDvMapTexture;
#endif
+
+#ifdef APPLY_EYEDOT
+uniform sampler2D u_NormalmapTexture;
#endif
-#endif
-#endif
+uniform sampler2D u_ReflectionTexture;
+uniform sampler2D u_RefractionTexture;
+
+void main(void)
+{
+ myhalf3 color;
-#ifdef APPLY_SPECULAR
+#ifdef APPLY_DUDV
+ vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25)));
+ vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2);
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ vec3 fdist = vec3(0.0);
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ // get projective texcoords
+ float scale = float(1.0 / float(v_ProjVector.w));
+ float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width
+ float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height
+ vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
+ projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
+ projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ myhalf3 refr = myhalf3(0.0);
+ myhalf3 refl = myhalf3(0.0);
+
+#ifdef APPLY_EYEDOT
+ // calculate dot product between the surface normal and eye vector
+ // great for simulating qf_varying water translucency based on the view angle
+ myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5));
+ vec3 eyeNormal = normalize(myhalf3(v_EyeVector));
+
+ float refrdot = float(dot(surfaceNormal, eyeNormal));
+ //refrdot = float (clamp (refrdot, 0.0, 1.0));
+ float refldot = 1.0 - refrdot;
+ // get refraction and reflection
+
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot;
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
+
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord)));
#endif
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord)));
+#endif
+
+#endif // APPLY_EYEDOT
+
+ // add reflection and refraction
+#ifdef APPLY_DISTORTION_ALPHA
+ color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a)));
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf3(qf_FrontColor.rgb) + refr + refl;
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#ifdef APPLY_GREYSCALE
+ qf_FragColor = vec4(vec3(Greyscale(color)),1.0);
#else
-gl_FragColor = vec4(color);
+ qf_FragColor = vec4(vec3(color),1.0);
#endif
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/40.shader_test b/shaders/warsow/40.shader_test
index de4bd35..1c9c4a9 100644
--- a/shaders/warsow/40.shader_test
+++ b/shaders/warsow/40.shader_test
@@ -1,697 +1,1751 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
-
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
}
+
+
+#endif
+
+#endif
#endif
-void main()
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+qf_varying vec3 v_Position;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-#ifdef APPLY_LIGHTSTYLE0
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#define NORMALIZE_DIFFUSE_NORMAL
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
#endif
-#ifdef APPLY_SPECULAR
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
#else
-gl_FragColor = vec4(color);
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-void main()
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
-
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+ falloff *= falloff;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
}
+
+
+#endif
+
#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-void main()
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+qf_varying vec3 v_Position;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+qf_varying vec2 v_TexCoord;
#endif
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
-#ifdef APPLY_LIGHTSTYLE0
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
#endif
+
#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-#ifdef APPLY_SPECULAR
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
}
+
#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
#else
-gl_FragColor = vec4(color);
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/43.shader_test b/shaders/warsow/43.shader_test
index 4a2358e..1efcfe9 100644
--- a/shaders/warsow/43.shader_test
+++ b/shaders/warsow/43.shader_test
@@ -1,693 +1,1751 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_DIRECTIONAL_LIGHT
-#define APPLY_CELLSHADING
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
-
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
}
+
+
+#endif
+
+#endif
#endif
-void main()
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+qf_varying vec3 v_Position;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-#ifdef APPLY_LIGHTSTYLE0
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#define NORMALIZE_DIFFUSE_NORMAL
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
#endif
-#ifdef APPLY_SPECULAR
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
#else
-gl_FragColor = vec4(color);
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_DIRECTIONAL_LIGHT
-#define APPLY_CELLSHADING
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-void main()
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
-
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_CONST
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+ falloff *= falloff;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
}
+
+
+#endif
+
#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-void main()
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+qf_varying vec3 v_Position;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+qf_varying vec2 v_TexCoord;
#endif
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
-#ifdef APPLY_LIGHTSTYLE0
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
#endif
+
#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-#ifdef APPLY_SPECULAR
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
}
+
#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
#else
-gl_FragColor = vec4(color);
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/46.shader_test b/shaders/warsow/46.shader_test
index 76c961a..24e5790 100644
--- a/shaders/warsow/46.shader_test
+++ b/shaders/warsow/46.shader_test
@@ -1,307 +1,1753 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec4 TexCoord;
-varying vec4 ProjVector;
-#ifdef APPLY_EYEDOT
-varying vec3 EyeVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-#ifdef APPLY_EYEDOT
-uniform vec3 EyeOrigin;
-uniform float FrontPlane;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
-TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-textureMatrix = gl_TextureMatrix[0];
-textureMatrix[0] = -textureMatrix[0];
-textureMatrix[1] = -textureMatrix[1];
-TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_EYEDOT
-mat3 strMatrix;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_Position = ftransform();
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-#ifdef APPLY_DUDV
-uniform sampler2D DuDvMapTexture;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-#ifdef APPLY_EYEDOT
-uniform sampler2D NormalmapTexture;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-uniform sampler2D ReflectionTexture;
-uniform sampler2D RefractionTexture;
-uniform float TextureWidth, TextureHeight;
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-myhalf3 color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_DUDV
-vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));
-vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-vec3 fdist = vec3(0.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
-// get projective texcoords
-float scale = float(1.0 / float(ProjVector.w));
-float inv2NW = 1.0 / (2.0 * float (TextureWidth));
-float inv2NH = 1.0 / (2.0 * float (TextureHeight));
-vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
-projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
-projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+uniform float u_MirrorSide;
-myhalf3 refr = myhalf3(0.0);
-myhalf3 refl = myhalf3(0.0);
+uniform float u_ZNear, u_ZFar;
-#ifdef APPLY_EYEDOT
-// calculate dot product between the surface normal and eye vector
-// great for simulating varying water translucency based on the view angle
-myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5));
-vec3 eyeNormal = normalize(myhalf3(EyeVector));
+uniform ivec4 u_Viewport; // x, y, width, height
-float refrdot = float(dot(surfaceNormal, eyeNormal));
-//refrdot = float (clamp (refrdot, 0.0, 1.0));
-float refldot = 1.0 - refrdot;
-// get refraction and reflection
+uniform vec4 u_TextureParams;
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot;
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot;
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord)));
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord)));
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
#endif
#endif
+#endif
-// add reflection and refraction
-#ifdef APPLY_DISTORTION_ALPHA
-color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color = myhalf3(gl_Color.rgb) + refr + refl;
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),1.0);
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
#else
-gl_FragColor = vec4(vec3(color),1.0);
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
}
-#endif // FRAGMENT_SHADER
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
-#if !defined(__GLSL_CG_DATA_TYPES)
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying vec4 TexCoord;
-varying vec4 ProjVector;
-#ifdef APPLY_EYEDOT
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_EYEDOT
-uniform vec3 EyeOrigin;
-uniform float FrontPlane;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
-TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-textureMatrix = gl_TextureMatrix[0];
-textureMatrix[0] = -textureMatrix[0];
-textureMatrix[1] = -textureMatrix[1];
-TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_EYEDOT
-mat3 strMatrix;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_Position = ftransform();
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-#ifdef APPLY_DUDV
-uniform sampler2D DuDvMapTexture;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-#ifdef APPLY_EYEDOT
-uniform sampler2D NormalmapTexture;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-uniform sampler2D ReflectionTexture;
-uniform sampler2D RefractionTexture;
-uniform float TextureWidth, TextureHeight;
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
{
-myhalf3 color;
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
-#ifdef APPLY_DUDV
-vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));
-vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-vec3 fdist = vec3(0.0);
+qf_varying vec2 v_TexCoord;
#endif
-// get projective texcoords
-float scale = float(1.0 / float(ProjVector.w));
-float inv2NW = 1.0 / (2.0 * float (TextureWidth));
-float inv2NH = 1.0 / (2.0 * float (TextureHeight));
-vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
-projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
-projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
-myhalf3 refr = myhalf3(0.0);
-myhalf3 refl = myhalf3(0.0);
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-#ifdef APPLY_EYEDOT
-// calculate dot product between the surface normal and eye vector
-// great for simulating varying water translucency based on the view angle
-myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5));
-vec3 eyeNormal = normalize(myhalf3(EyeVector));
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-float refrdot = float(dot(surfaceNormal, eyeNormal));
-//refrdot = float (clamp (refrdot, 0.0, 1.0));
-float refldot = 1.0 - refrdot;
-// get refraction and reflection
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot;
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord)));
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord)));
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-// add reflection and refraction
-#ifdef APPLY_DISTORTION_ALPHA
-color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-color = myhalf3(gl_Color.rgb) + refr + refl;
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),1.0);
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-gl_FragColor = vec4(vec3(color),1.0);
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
}
-#endif // FRAGMENT_SHADER
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/49.shader_test b/shaders/warsow/49.shader_test
index 9b644bc..b9f25bd 100644
--- a/shaders/warsow/49.shader_test
+++ b/shaders/warsow/49.shader_test
@@ -1,225 +1,2063 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec4 ProjVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-void main(void)
+if (numWeights > 2)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-mat4 textureMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-textureMatrix = gl_TextureMatrix[0];
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-gl_Position = ftransform();
-ProjVector = textureMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_SPECULAR
+#define APPLY_DECAL
+#define APPLY_DECAL_ADD
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform myhalf3 LightAmbient;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
-uniform float TextureWidth, TextureHeight;
-uniform float ProjDistance;
-uniform sampler2DShadow ShadowmapTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
-void main(void)
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
{
-myhalf color = myhalf(1.0);
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
-if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance)
-discard;
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
-float dtW = 1.0 / TextureWidth;
-float dtH = 1.0 / TextureHeight;
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
-vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);
-coord = (coord + vec3 (1.0)) * vec3 (0.5);
-coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));
-coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));
-coord.r = float (clamp (float(coord.r), 0.0, 1.0));
+ myhalf3 weightedDiffuseNormalModelspace;
-myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r);
-myhalf shadow = shadow0;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
-#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
-vec3 coord2 = coord + vec3(0.0, dtH, 0.0);
-myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
-coord2 = coord + vec3(dtW, dtH, 0.0);
-myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT
-coord2 = coord + vec3(dtW, 0.0, 0.0);
-myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-#if defined(APPLY_PCF3x3)
-coord2 = coord + vec3(-dtW, 0.0, 0.0);
-myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(-dtW, -dtH, 0.0);
-myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(0.0, -dtH, 0.0);
-myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(dtW, -dtH, 0.0);
-myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-coord2 = coord + vec3(-dtW, dtH, 0.0);
-myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11);
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25);
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-shadow = shadow0;
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
-float attenuation = float (ProjVector.w) / ProjDistance;
-myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z))
-;compensation = max (compensation, 0.0);
-color = shadow + attenuation + compensation;
+#endif // APPLY_DECAL
-gl_FragColor = vec4(vec3(color),1.0);
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec4 ProjVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-mat4 textureMatrix;
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-textureMatrix = gl_TextureMatrix[0];
+vec4 DQReal1, DQDual1;
+float scale;
-gl_Position = ftransform();
-ProjVector = textureMatrix * gl_Vertex;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_SPECULAR
+#define APPLY_DECAL
+#define APPLY_DECAL_ADD
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform myhalf3 LightAmbient;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
-uniform float TextureWidth, TextureHeight;
-uniform float ProjDistance;
-uniform sampler2DShadow ShadowmapTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
-void main(void)
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
{
-myhalf color = myhalf(1.0);
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
-if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance)
-discard;
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
-float dtW = 1.0 / TextureWidth;
-float dtH = 1.0 / TextureHeight;
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
-vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);
-coord = (coord + vec3 (1.0)) * vec3 (0.5);
-coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));
-coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));
-coord.r = float (clamp (float(coord.r), 0.0, 1.0));
+ myhalf3 weightedDiffuseNormalModelspace;
-myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r);
-myhalf shadow = shadow0;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
-#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
-vec3 coord2 = coord + vec3(0.0, dtH, 0.0);
-myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
-coord2 = coord + vec3(dtW, dtH, 0.0);
-myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT
-coord2 = coord + vec3(dtW, 0.0, 0.0);
-myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-#if defined(APPLY_PCF3x3)
-coord2 = coord + vec3(-dtW, 0.0, 0.0);
-myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(-dtW, -dtH, 0.0);
-myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(0.0, -dtH, 0.0);
-myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(dtW, -dtH, 0.0);
-myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-coord2 = coord + vec3(-dtW, dtH, 0.0);
-myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11);
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25);
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-shadow = shadow0;
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
-float attenuation = float (ProjVector.w) / ProjDistance;
-myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z))
-;compensation = max (compensation, 0.0);
-color = shadow + attenuation + compensation;
+#endif // APPLY_DECAL
-gl_FragColor = vec4(vec3(color),1.0);
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/52.shader_test b/shaders/warsow/52.shader_test
index b4f6f7c..5504683 100644
--- a/shaders/warsow/52.shader_test
+++ b/shaders/warsow/52.shader_test
@@ -1,103 +1,2059 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 ProjVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-uniform float OutlineHeight;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-void main(void)
+if (numWeights > 2)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-vec4 n = vec4(gl_Normal.xyz, 0.0);
-vec4 v = vec4(gl_Vertex) + n * OutlineHeight;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-gl_Position = gl_ModelViewProjectionMatrix * v;
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * v;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform float OutlineCutOff;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-void main(void)
+void main()
{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
-#ifdef APPLY_OUTLINES_CUTOFF
-if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff))
-discard;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-gl_FragColor = vec4 (gl_Color);
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 ProjVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float OutlineHeight;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-vec4 n = vec4(gl_Normal.xyz, 0.0);
-vec4 v = vec4(gl_Vertex) + n * OutlineHeight;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-gl_Position = gl_ModelViewProjectionMatrix * v;
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * v;
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform float OutlineCutOff;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-void main(void)
+void main()
{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
-#ifdef APPLY_OUTLINES_CUTOFF
-if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff))
-discard;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-gl_FragColor = vec4 (gl_Color);
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/55.shader_test b/shaders/warsow/55.shader_test
index 3e97234..19edae8 100644
--- a/shaders/warsow/55.shader_test
+++ b/shaders/warsow/55.shader_test
@@ -1,140 +1,1281 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
#define M_TWOPI 6.28318530717958647692
+#endif
-varying vec2 TexCoord;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float TurbAmplitude, TurbPhase;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-vec4 turb;
-turb = vec4(gl_MultiTexCoord0);
-turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI );
-turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI );
-TexCoord = vec2(gl_TextureMatrix[0] * turb);
+vec4 DQReal1, DQDual1;
+float scale;
-gl_Position = ftransform();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DUDV
+#define APPLY_DISTORTION_ALPHA
+#define APPLY_REFRACTION
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+
+qf_varying vec4 v_TexCoord;
+qf_varying vec4 v_ProjVector;
+#ifdef APPLY_EYEDOT
+qf_varying vec3 v_EyeVector;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#ifdef APPLY_EYEDOT
+uniform float u_FrontPlane;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor));
+
+ v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+ vec2 textureMatrix3_[3];
+ textureMatrix3_[0] = u_TextureMatrix[0];
+ textureMatrix3_[1] = u_TextureMatrix[1];
+ textureMatrix3_[2] = -u_TextureMatrix[2];
+ v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord);
+
+#ifdef APPLY_EYEDOT
+ mat3 v_StrMatrix;
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+ vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+ v_ProjVector = gl_Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform sampler2D BaseTexture;
+#ifdef APPLY_DUDV
+uniform sampler2D u_DuDvMapTexture;
+#endif
+
+#ifdef APPLY_EYEDOT
+uniform sampler2D u_NormalmapTexture;
+#endif
+uniform sampler2D u_ReflectionTexture;
+uniform sampler2D u_RefractionTexture;
void main(void)
{
+ myhalf3 color;
-myhalf4 color;
+#ifdef APPLY_DUDV
+ vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25)));
+ vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2);
-color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord));
+ vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+#else
+ vec3 fdist = vec3(0.0);
+#endif
-gl_FragColor = vec4(color);
-}
+ // get projective texcoords
+ float scale = float(1.0 / float(v_ProjVector.w));
+ float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width
+ float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height
+ vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
+ projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
+ projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
-#endif // FRAGMENT_SHADER
+ myhalf3 refr = myhalf3(0.0);
+ myhalf3 refl = myhalf3(0.0);
+#ifdef APPLY_EYEDOT
+ // calculate dot product between the surface normal and eye vector
+ // great for simulating qf_varying water translucency based on the view angle
+ myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5));
+ vec3 eyeNormal = normalize(myhalf3(v_EyeVector));
-
-=====================================
-wdm16
-
-Silver connected from 127.0.0.1
-Silver skill 50
-Sector connected from 127.0.0.1
-Sector skill 50
+ float refrdot = float(dot(surfaceNormal, eyeNormal));
+ //refrdot = float (clamp (refrdot, 0.0, 1.0));
+ float refldot = 1.0 - refrdot;
+ // get refraction and reflection
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot;
+#endif
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot;
+#endif
+
+#else
+
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord)));
+#endif
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord)));
+#endif
+
+#endif // APPLY_EYEDOT
+
+ // add reflection and refraction
+#ifdef APPLY_DISTORTION_ALPHA
+ color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a)));
+#else
+ color = myhalf3(qf_FrontColor.rgb) + refr + refl;
+#endif
+
+#ifdef APPLY_GREYSCALE
+ qf_FragColor = vec4(vec3(Greyscale(color)),1.0);
+#else
+ qf_FragColor = vec4(vec3(color),1.0);
+#endif
+}
-#if !defined(__GLSL_CG_DATA_TYPES)
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
#define M_TWOPI 6.28318530717958647692
+#endif
-varying vec2 TexCoord;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float TurbAmplitude, TurbPhase;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-vec4 turb;
-turb = vec4(gl_MultiTexCoord0);
-turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI );
-turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI );
-TexCoord = vec2(gl_TextureMatrix[0] * turb);
+vec4 DQReal1, DQDual1;
+float scale;
-gl_Position = ftransform();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DUDV
+#define APPLY_DISTORTION_ALPHA
+#define APPLY_REFRACTION
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+
+qf_varying vec4 v_TexCoord;
+qf_varying vec4 v_ProjVector;
+#ifdef APPLY_EYEDOT
+qf_varying vec3 v_EyeVector;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#ifdef APPLY_EYEDOT
+uniform float u_FrontPlane;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor));
+
+ v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+ vec2 textureMatrix3_[3];
+ textureMatrix3_[0] = u_TextureMatrix[0];
+ textureMatrix3_[1] = u_TextureMatrix[1];
+ textureMatrix3_[2] = -u_TextureMatrix[2];
+ v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord);
+
+#ifdef APPLY_EYEDOT
+ mat3 v_StrMatrix;
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+ vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+ v_ProjVector = gl_Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform sampler2D BaseTexture;
+#ifdef APPLY_DUDV
+uniform sampler2D u_DuDvMapTexture;
+#endif
+
+#ifdef APPLY_EYEDOT
+uniform sampler2D u_NormalmapTexture;
+#endif
+uniform sampler2D u_ReflectionTexture;
+uniform sampler2D u_RefractionTexture;
void main(void)
{
+ myhalf3 color;
+
+#ifdef APPLY_DUDV
+ vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25)));
+ vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2);
+
+ vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+#else
+ vec3 fdist = vec3(0.0);
+#endif
+
+ // get projective texcoords
+ float scale = float(1.0 / float(v_ProjVector.w));
+ float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width
+ float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height
+ vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
+ projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
+ projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+
+ myhalf3 refr = myhalf3(0.0);
+ myhalf3 refl = myhalf3(0.0);
+
+#ifdef APPLY_EYEDOT
+ // calculate dot product between the surface normal and eye vector
+ // great for simulating qf_varying water translucency based on the view angle
+ myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5));
+ vec3 eyeNormal = normalize(myhalf3(v_EyeVector));
+
+ float refrdot = float(dot(surfaceNormal, eyeNormal));
+ //refrdot = float (clamp (refrdot, 0.0, 1.0));
+ float refldot = 1.0 - refrdot;
+ // get refraction and reflection
-myhalf4 color;
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot;
+#endif
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot;
+#endif
+
+#else
+
+#ifdef APPLY_REFRACTION
+ refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord)));
+#endif
+#ifdef APPLY_REFLECTION
+ refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord)));
+#endif
-color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord));
+#endif // APPLY_EYEDOT
-gl_FragColor = vec4(color);
+ // add reflection and refraction
+#ifdef APPLY_DISTORTION_ALPHA
+ color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a)));
+#else
+ color = myhalf3(qf_FrontColor.rgb) + refr + refl;
+#endif
+
+#ifdef APPLY_GREYSCALE
+ qf_FragColor = vec4(vec3(Greyscale(color)),1.0);
+#else
+ qf_FragColor = vec4(vec3(color),1.0);
+#endif
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/58.shader_test b/shaders/warsow/58.shader_test
new file mode 100644
index 0000000..ee0f427
--- /dev/null
+++ b/shaders/warsow/58.shader_test
@@ -0,0 +1,1751 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec3 v_Position;
+
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
+
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
+
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
+#else
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
+#endif
+
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
+
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
+#else
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
+{
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
+}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
+#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#else
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+#endif
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/60.shader_test b/shaders/warsow/60.shader_test
deleted file mode 100644
index 30ba541..0000000
--- a/shaders/warsow/60.shader_test
+++ /dev/null
@@ -1,17 +0,0 @@
-[require]
-GLSL >= 1.10
-
-[fragment shader]
-uniform vec4 color;
-void main()
-{
- gl_FragColor = color;
-}
-
-[vertex shader]
-attribute vec4 position;
-void main()
-{
- gl_Position = position;
-}
-
diff --git a/shaders/warsow/61.shader_test b/shaders/warsow/61.shader_test
new file mode 100644
index 0000000..62f4076
--- /dev/null
+++ b/shaders/warsow/61.shader_test
@@ -0,0 +1,2057 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/63.shader_test b/shaders/warsow/63.shader_test
deleted file mode 100644
index 7497b6b..0000000
--- a/shaders/warsow/63.shader_test
+++ /dev/null
@@ -1,22 +0,0 @@
-[require]
-GLSL >= 1.10
-
-[fragment shader]
-#version 130
-uniform ivec4 color;
-out ivec4 out_color;
-
-void main()
-{
- out_color = color;
-}
-
-[vertex shader]
-#version 130
-in vec4 position;
-void main()
-{
- gl_Position = position;
-}
-
-
diff --git a/shaders/warsow/64.shader_test b/shaders/warsow/64.shader_test
index b59d973..8033677 100644
--- a/shaders/warsow/64.shader_test
+++ b/shaders/warsow/64.shader_test
@@ -1,696 +1,1755 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
-
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
}
+
+
+#endif
+
+#endif
#endif
-void main()
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+qf_varying vec3 v_Position;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-#ifdef APPLY_LIGHTSTYLE0
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#define NORMALIZE_DIFFUSE_NORMAL
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
#endif
-#ifdef APPLY_SPECULAR
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
#else
-gl_FragColor = vec4(color);
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
-}
-#endif // FRAGMENT_SHADER
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+ color *= diffuse;
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
+}
-#if !defined(__GLSL_CG_DATA_TYPES)
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
-
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_RGB_DISTANCERAMP
+#define APPLY_ALPHA_CONST
+#define APPLY_SOFT_PARTICLE
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
}
+
+
+#endif
+
+#endif
#endif
-void main()
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
-#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#endif
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+qf_varying vec3 v_Position;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DRAWFLAT
+qf_varying myhalf v_NormalZ;
+#endif
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+#ifdef APPLY_TC_GEN_REFLECTION
+#define APPLY_CUBEMAP
+#endif
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#ifdef APPLY_CUBEMAP
+qf_varying vec3 v_TexCoord;
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+qf_varying vec2 v_TexCoord;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(APPLY_SOFT_PARTICLE)
+qf_varying float v_Depth;
+#endif
-#ifdef APPLY_LIGHTSTYLE0
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#define NORMALIZE_DIFFUSE_NORMAL
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+#if defined(APPLY_TC_GEN_REFLECTION)
+uniform mat4 u_ReflectionTexMatrix;
+#elif defined(APPLY_TC_GEN_VECTOR)
+uniform mat4 u_VectorTexMatrix;
#endif
-#ifdef APPLY_SPECULAR
+void main(void)
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ qf_FrontColor = vec4(outColor);
+
+#if defined(APPLY_TC_GEN_ENV)
+ vec3 Projection;
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+ Projection = u_EntityDist - Position.xyz;
+ Projection = normalize(Projection);
+
+ float Depth = dot(Normal.xyz, Projection) * 2.0;
+ v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5);
+#elif defined(APPLY_TC_GEN_VECTOR)
+ v_TexCoord = vec2(u_VectorTexMatrix * Position);
+#elif defined(APPLY_TC_GEN_REFLECTION)
+ v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0));
+#elif defined(APPLY_TC_GEN_PROJECTION)
+ v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+#endif // defined(APPLY_TC_GEN_ENV)
+
+ v_Position = Position.xyz;
+
+#ifdef APPLY_DRAWFLAT
+ v_NormalZ = Normal.z;
+#endif
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+#if defined(APPLY_SOFT_PARTICLE)
+ vec4 modelPos = u_ModelViewMatrix * Position;
+ v_Depth = -modelPos.z;
+#endif
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef APPLY_CUBEMAP
+uniform samplerCube u_BaseTexture;
+#else
+uniform sampler2D u_BaseTexture;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef NUM_LIGHTMAPS
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+#if defined(APPLY_SOFT_PARTICLE)
+#ifdef FRAGMENT_SHADER
+
+myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec2 tc = ScreenCoord * u_TextureParams.zw;
+
+ myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear));
+ myhalf partdepth = Depth;
+
+ myhalf d = max((fragdepth - partdepth) * Scale, 0.0);
+ myhalf softness = 1.0 - min(1.0, d);
+
+ softness *= softness;
+ softness = 1.0 - softness * softness;
+ return softness;
}
+
+#endif
+
+
+uniform sampler2D u_DepthTexture;
+
#endif
+
+void main(void)
+{
+ myhalf4 color;
+
+#ifdef NUM_LIGHTMAPS
+ color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a);
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0];
+#if NUM_LIGHTMAPS >= 2
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1];
+#if NUM_LIGHTMAPS >= 3
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2];
+#if NUM_LIGHTMAPS >= 4
+ color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3];
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
#else
-color = color * myhalf4(gl_Color.rgba);
+ color = myhalf4(qf_FrontColor);
+#endif // NUM_LIGHTMAPS
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position);
+#endif
+
+ myhalf4 diffuse;
+
+#ifdef APPLY_CUBEMAP
+ diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord));
#else
-gl_FragColor = vec4(color);
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ)));
+ diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n));
+#endif
+
+ color *= diffuse;
+
+#ifdef NUM_LIGHTMAPS
+ // so that team-colored shaders work
+ color *= myhalf4(qf_FrontColor);
+#endif
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+#if defined(APPLY_SOFT_PARTICLE)
+ myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale);
+ color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/67.shader_test b/shaders/warsow/67.shader_test
index f005219..4d04939 100644
--- a/shaders/warsow/67.shader_test
+++ b/shaders/warsow/67.shader_test
@@ -1,138 +1,772 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -140,342 +774,1028 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-gl_FragColor = vec4(color);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
}
-#endif // FRAGMENT_SHADER
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#endif
+#endif
-#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-uniform vec3 EyeOrigin;
+uniform Fog u_Fog;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -483,207 +1803,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
-#ifdef APPLY_LIGHTSTYLE0
+ // deluxemapping using light vectors in modelspace
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/7.shader_test b/shaders/warsow/7.shader_test
index 6e68fc9..b100519 100644
--- a/shaders/warsow/7.shader_test
+++ b/shaders/warsow/7.shader_test
@@ -1,695 +1,979 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
-#endif
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
-// deluxemapping using light vectors in modelspace
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
-#ifdef APPLY_LIGHTSTYLE0
+uniform myhalf2 u_BlendMix;
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+uniform float u_MirrorSide;
-#define NORMALIZE_DIFFUSE_NORMAL
+uniform float u_ZNear, u_ZFar;
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+uniform ivec4 u_Viewport; // x, y, width, height
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
+uniform vec4 u_TextureParams;
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+qf_varying float v_Depth;
-#endif
-#endif
-#endif
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_SPECULAR
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+ v_Depth = gl_Position.z;
}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
-#endif
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+void main(void)
+{
+ qf_FragColor = encodedepthmacro(v_Depth);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
-#endif
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
-// deluxemapping using light vectors in modelspace
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
-#ifdef APPLY_LIGHTSTYLE0
+uniform myhalf2 u_BlendMix;
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+uniform float u_MirrorSide;
-#define NORMALIZE_DIFFUSE_NORMAL
+uniform float u_ZNear, u_ZFar;
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+uniform ivec4 u_Viewport; // x, y, width, height
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
+uniform vec4 u_TextureParams;
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+uniform myhalf u_SoftParticlesScale;
+#ifndef decodedepthmacro
+// Lifted from Darkplaces shader program
+#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))
+#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+qf_varying float v_Depth;
-#endif
-#endif
-#endif
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_SPECULAR
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+ v_Depth = gl_Position.z;
}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
-#endif
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+void main(void)
+{
+ qf_FragColor = encodedepthmacro(v_Depth);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/70.shader_test b/shaders/warsow/70.shader_test
index 62d5d00..96f5d3c 100644
--- a/shaders/warsow/70.shader_test
+++ b/shaders/warsow/70.shader_test
@@ -1,691 +1,1239 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE0
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_SPECULAR
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform float u_OutlineHeight;
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
#endif
+ qf_FragColor = vec4(qf_FrontColor);
}
#endif // FRAGMENT_SHADER
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-// Warsow GLSL shader
+[fragment shader]
+#version 130
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define NUM_BONE_INFLUENCES 3
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE0
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_SPECULAR
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform float u_OutlineHeight;
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
#endif
+ qf_FragColor = vec4(qf_FrontColor);
}
#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/73.shader_test b/shaders/warsow/73.shader_test
index 6e68fc9..879331b 100644
--- a/shaders/warsow/73.shader_test
+++ b/shaders/warsow/73.shader_test
@@ -1,141 +1,772 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DECAL
+#define APPLY_HALFLAMBERT
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -143,345 +774,1028 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-gl_FragColor = vec4(color);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
}
-#endif // FRAGMENT_SHADER
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_DECAL
+#define APPLY_HALFLAMBERT
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-// Warsow GLSL shader
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#endif
+#endif
-#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-uniform vec3 EyeOrigin;
+uniform Fog u_Fog;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -489,207 +1803,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
-#ifdef APPLY_LIGHTSTYLE0
+ // deluxemapping using light vectors in modelspace
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/76.shader_test b/shaders/warsow/76.shader_test
index de4bd35..6e73a4e 100644
--- a/shaders/warsow/76.shader_test
+++ b/shaders/warsow/76.shader_test
@@ -1,695 +1,1239 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE0
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_SPECULAR
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform float u_OutlineHeight;
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
#endif
+ qf_FragColor = vec4(qf_FrontColor);
}
#endif // FRAGMENT_SHADER
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_LIGHTSTYLE0
-#define APPLY_FBLIGHTMAP
-#define APPLY_SPECULAR
-#define APPLY_AMBIENT_COMPENSATION
-// Warsow GLSL shader
+[fragment shader]
+#version 130
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main()
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
-#endif
-#endif
-#endif
-#endif
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-}
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#endif // VERTEX_SHADER
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
-#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
-#endif
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
-#endif
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
-#endif
+vec4 DQReal1, DQDual1;
+float scale;
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
-// The credit goes to LordHavoc (as always)
-vec2 OffsetMapping(vec2 TexCoord)
+if (numWeights > 2)
{
-#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-void main()
-{
-#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
-#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define NUM_BONE_INFLUENCES 2
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+uniform float u_ShaderTime;
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
-#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
#endif
-// deluxemapping using light vectors in modelspace
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE0
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
-#else
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#define NORMALIZE_DIFFUSE_NORMAL
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
#endif
-#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_SPECULAR
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
-#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
-#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
-#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+
+uniform float u_OutlineHeight;
+
+void main(void)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
-#else
-color = color * myhalf4(gl_Color.rgba);
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ vec2 TexCoord = a_TexCoord;
+ myhalf4 inColor = myhalf4(a_Color);
+
+ TransformVerts(Position, Normal, TexCoord);
+
+ Position += vec4(Normal * u_OutlineHeight, 0.0);
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+ myhalf4 tempColor = myhalf4(1.0);
+ FogGen(Position, tempColor, myhalf2(0.0, 1.0));
+ outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
-#else
-gl_FragColor = vec4(color);
+ qf_FrontColor = vec4(outColor);
+}
+
+#endif // VERTEX_SHADER
+
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+uniform float u_OutlineCutOff;
+
+void main(void)
+{
+#ifdef APPLY_OUTLINES_CUTOFF
+ if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff))
+ discard;
#endif
+ qf_FragColor = vec4(qf_FrontColor);
}
#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/79.shader_test b/shaders/warsow/79.shader_test
index 4a2358e..27bb40d 100644
--- a/shaders/warsow/79.shader_test
+++ b/shaders/warsow/79.shader_test
@@ -1,140 +1,772 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-#define APPLY_DIRECTIONAL_LIGHT
-#define APPLY_CELLSHADING
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform vec3 EyeOrigin;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main()
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -142,344 +774,1028 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
-#ifdef APPLY_LIGHTSTYLE0
+#endif // APPLY_DIRECTIONAL_LIGHT
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
#endif
-#ifdef APPLY_SPECULAR
+ qf_FragColor = vec4(color);
+}
-#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-#ifdef APPLY_DECAL
-#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
#else
-color = color * myhalf4(gl_Color.rgba);
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-gl_FragColor = vec4(color);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
}
-#endif // FRAGMENT_SHADER
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
-[vertex shader]
-#define VERTEX_SHADER
-#define APPLY_DIRECTIONAL_LIGHT
-#define APPLY_CELLSHADING
-// Warsow GLSL shader
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-#if !defined(__GLSL_CG_DATA_TYPES)
-#define myhalf float
-#define myhalf2 vec2
-#define myhalf3 vec3
-#define myhalf4 vec4
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-varying vec2 TexCoord;
-#ifdef APPLY_LIGHTSTYLE0
-varying vec4 LightmapTexCoord01;
-#ifdef APPLY_LIGHTSTYLE2
-varying vec4 LightmapTexCoord23;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
-#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-varying vec3 EyeVector;
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
-#ifdef APPLY_DIRECTIONAL_LIGHT
-varying vec3 LightVector;
#endif
-varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+#endif
+#endif
-#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
-uniform vec3 EyeOrigin;
+uniform Fog u_Fog;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform vec3 LightDir;
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-void main()
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
{
-gl_FrontColor = gl_Color;
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
-TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-LightmapTexCoord01.st = gl_MultiTexCoord4.st;
-#ifdef APPLY_LIGHTSTYLE1
-LightmapTexCoord01.pq = gl_MultiTexCoord5.st;
-#ifdef APPLY_LIGHTSTYLE2
-LightmapTexCoord23.st = gl_MultiTexCoord6.st;
-#ifdef APPLY_LIGHTSTYLE3
-LightmapTexCoord23.pq = gl_MultiTexCoord7.st;
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
#endif
+}
+
#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
#endif
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+qf_varying vec3 v_Position;
#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;
-EyeVector = EyeVectorWorld * strMatrix;
+qf_varying vec3 v_EyeVector;
#endif
-#ifdef APPLY_DIRECTIONAL_LIGHT
-LightVector = LightDir * strMatrix;
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-gl_Position = ftransform ();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
}
-#endif // VERTEX_SHADER
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
-#ifdef APPLY_LIGHTSTYLE0
-uniform sampler2D LightmapTexture0;
-uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord
-uniform myhalf3 lsColor0; // lightstyle color
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
-#ifdef APPLY_LIGHTSTYLE1
-uniform sampler2D LightmapTexture1;
-uniform float DeluxemapOffset1;
-uniform myhalf3 lsColor1;
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
-#ifdef APPLY_LIGHTSTYLE2
-uniform sampler2D LightmapTexture2;
-uniform float DeluxemapOffset2;
-uniform myhalf3 lsColor2;
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
-#ifdef APPLY_LIGHTSTYLE3
-uniform sampler2D LightmapTexture3;
-uniform float DeluxemapOffset3;
-uniform myhalf3 lsColor3;
+#endif
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
#endif
-uniform sampler2D BaseTexture;
-uniform sampler2D NormalmapTexture;
-uniform sampler2D GlossTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
#ifdef APPLY_DECAL
-uniform sampler2D DecalTexture;
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
#endif
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-uniform float OffsetMappingScale;
+uniform float u_OffsetMappingScale;
#endif
-uniform myhalf3 LightAmbient;
-#ifdef APPLY_DIRECTIONAL_LIGHT
-uniform myhalf3 LightDiffuse;
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
#endif
-uniform myhalf GlossIntensity; // gloss scaling factor
-uniform myhalf GlossExponent; // gloss exponent factor
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
@@ -487,207 +1803,259 @@ uniform myhalf GlossExponent; // gloss exponent factor
vec2 OffsetMapping(vec2 TexCoord)
{
#ifdef APPLY_RELIEFMAPPING
-// 14 sample relief mapping: linear search and then binary search
-// this basically steps forward a small amount repeatedly until it finds
-// itself inside solid, then jitters forward and back using decreasing
-// amounts to find the impact
-//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);
-//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);
-vec3 RT = vec3(TexCoord, 1);
-OffsetVector *= 0.1;
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
-RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
-return RT.xy;
-#else
-// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
-// this basically moves forward the full distance, and then backs up based
-// on height of samples
-//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));
-//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));
-vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));
-TexCoord += OffsetVector;
-OffsetVector *= 0.5;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;
-return TexCoord;
-#endif
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
}
-#endif
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
void main()
{
#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-// apply offsetmapping
-vec2 TexCoordOffset = OffsetMapping(TexCoord);
-#define TexCoord TexCoordOffset
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
#endif
-myhalf3 surfaceNormal;
-myhalf3 diffuseNormalModelspace;
-myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);
-float diffuseProduct;
-#ifdef APPLY_CELLSHADING
-int lightcell;
-float diffuseProductPositive;
-float diffuseProductNegative;
-float hardShadow;
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
#endif
-myhalf3 weightedDiffuseNormal;
-myhalf3 specularNormal;
-float specularProduct;
+ myhalf3 weightedDiffuseNormalModelspace;
-#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)
-myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
#else
-myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-// get the surface normal
-surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
#ifdef APPLY_DIRECTIONAL_LIGHT
-diffuseNormal = myhalf3 (LightVector);
-weightedDiffuseNormal = diffuseNormal;
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-#ifdef APPLY_CELLSHADING
-hardShadow = 0.0;
-diffuseProductPositive = max (diffuseProduct, 0.0);
-diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
-// smooth the hard shadow edge
-lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
-hardShadow += float(lightcell);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
-hardShadow += float(lightcell);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-lightcell = int(diffuseProductPositive * 2.0);
-hardShadow += float(lightcell);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-// backlight
-lightcell = int (diffuseProductNegative * 2.0);
-color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
#else
-color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;
-#endif
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
#endif
-// deluxemapping using light vectors in modelspace
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
-#ifdef APPLY_LIGHTSTYLE0
+ // deluxemapping using light vectors in modelspace
-// get light normal
-diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-// calculate directional shading
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
#ifdef APPLY_FBLIGHTMAP
-weightedDiffuseNormal = diffuseNormal;
-// apply lightmap color
-color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)));
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
#else
-
#define NORMALIZE_DIFFUSE_NORMAL
-
-weightedDiffuseNormal = lsColor0 * diffuseNormal;
-// apply lightmap color
-color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st));
-#endif
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
#ifdef APPLY_AMBIENT_COMPENSATION
-// compensate for ambient lighting
-color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;
-#endif
-
-#ifdef APPLY_LIGHTSTYLE1
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor1 * diffuseNormal;
-color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq));
-
-#ifdef APPLY_LIGHTSTYLE2
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor2 * diffuseNormal;
-color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st));
-
-#ifdef APPLY_LIGHTSTYLE3
-diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;
-diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));
-diffuseProduct = float (dot (surfaceNormal, diffuseNormal));
-weightedDiffuseNormal += lsColor3 * diffuseNormal;
-color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq));
-
-#endif
-#endif
-#endif
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
#endif
#ifdef APPLY_SPECULAR
#ifdef NORMALIZE_DIFFUSE_NORMAL
-specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
#else
-specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
#endif
-specularProduct = float (dot (surfaceNormal, specularNormal));
-color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);
-#endif
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
-#ifdef APPLY_BASETEX_ALPHA_ONLY
-color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
#else
-#ifdef APPLY_COLOR_CLAMPING
-color = min(color, myhalf4(1.0));
-#endif
-color = color * myhalf4(texture2D(BaseTexture, TexCoord));
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
#ifdef APPLY_DECAL
+
#ifdef APPLY_DECAL_ADD
-myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb + color.rgb;
-color.a = color.a * myhalf(gl_Color.a);
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-myhalf4 decal = myhalf4(gl_Color.rgba);
-if (decal.a > 0.0)
-{
-decal = decal * myhalf4(texture2D(DecalTexture, TexCoord));
-color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);
-}
-#endif
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
#else
-color = color * myhalf4(gl_Color.rgba);
-#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),color.a);
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
#else
-gl_FragColor = vec4(color);
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/82.shader_test b/shaders/warsow/82.shader_test
index 76c961a..14f0ec4 100644
--- a/shaders/warsow/82.shader_test
+++ b/shaders/warsow/82.shader_test
@@ -1,307 +1,2059 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 TexCoord;
-varying vec4 ProjVector;
-#ifdef APPLY_EYEDOT
-varying vec3 EyeVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-#ifdef APPLY_EYEDOT
-uniform vec3 EyeOrigin;
-uniform float FrontPlane;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
-TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-textureMatrix = gl_TextureMatrix[0];
-textureMatrix[0] = -textureMatrix[0];
-textureMatrix[1] = -textureMatrix[1];
-TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_EYEDOT
-mat3 strMatrix;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_Position = ftransform();
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-#ifdef APPLY_DUDV
-uniform sampler2D DuDvMapTexture;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-#ifdef APPLY_EYEDOT
-uniform sampler2D NormalmapTexture;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
#endif
-uniform sampler2D ReflectionTexture;
-uniform sampler2D RefractionTexture;
-uniform float TextureWidth, TextureHeight;
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-void main(void)
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
{
-myhalf3 color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-#ifdef APPLY_DUDV
-vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));
-vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-vec3 fdist = vec3(0.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
-// get projective texcoords
-float scale = float(1.0 / float(ProjVector.w));
-float inv2NW = 1.0 / (2.0 * float (TextureWidth));
-float inv2NH = 1.0 / (2.0 * float (TextureHeight));
-vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
-projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
-projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_RELIEFMAPPING
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
-myhalf3 refr = myhalf3(0.0);
-myhalf3 refl = myhalf3(0.0);
+uniform float u_ShaderTime;
-#ifdef APPLY_EYEDOT
-// calculate dot product between the surface normal and eye vector
-// great for simulating varying water translucency based on the view angle
-myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5));
-vec3 eyeNormal = normalize(myhalf3(EyeVector));
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-float refrdot = float(dot(surfaceNormal, eyeNormal));
-//refrdot = float (clamp (refrdot, 0.0, 1.0));
-float refldot = 1.0 - refrdot;
-// get refraction and reflection
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot;
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot;
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord)));
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord)));
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
#endif
+}
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
#endif
-// add reflection and refraction
-#ifdef APPLY_DISTORTION_ALPHA
-color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
#else
-color = myhalf3(gl_Color.rgb) + refr + refl;
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),1.0);
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-gl_FragColor = vec4(vec3(color),1.0);
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
}
-#endif // FRAGMENT_SHADER
+#endif // VERTEX_SHADER
+#ifdef FRAGMENT_SHADER
+// Fragment shader
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
-#if !defined(__GLSL_CG_DATA_TYPES)
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
#endif
-varying vec4 TexCoord;
-varying vec4 ProjVector;
-#ifdef APPLY_EYEDOT
-varying vec3 EyeVector;
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-#ifdef APPLY_EYEDOT
-uniform vec3 EyeOrigin;
-uniform float FrontPlane;
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main(void)
+if (numWeights > 1)
{
-gl_FrontColor = gl_Color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-mat4 textureMatrix;
+vec4 DQReal1, DQDual1;
+float scale;
-textureMatrix = gl_TextureMatrix[0];
-TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-textureMatrix = gl_TextureMatrix[0];
-textureMatrix[0] = -textureMatrix[0];
-textureMatrix[1] = -textureMatrix[1];
-TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-#ifdef APPLY_EYEDOT
-mat3 strMatrix;
-strMatrix[0] = gl_MultiTexCoord1.xyz;
-strMatrix[2] = gl_Normal.xyz;
-strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;
-EyeVector = EyeVectorWorld * strMatrix;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
-gl_Position = ftransform();
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-#ifdef FRAGMENT_SHADER
-// Fragment shader
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-#ifdef APPLY_DUDV
-uniform sampler2D DuDvMapTexture;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
+}
-#ifdef APPLY_EYEDOT
-uniform sampler2D NormalmapTexture;
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
#endif
-uniform sampler2D ReflectionTexture;
-uniform sampler2D RefractionTexture;
-uniform float TextureWidth, TextureHeight;
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-void main(void)
+if (numWeights > 1)
{
-myhalf3 color;
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-#ifdef APPLY_DUDV
-vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));
-vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);
+vec4 DQReal1, DQDual1;
+float scale;
-vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
#else
-vec3 fdist = vec3(0.0);
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
#endif
-// get projective texcoords
-float scale = float(1.0 / float(ProjVector.w));
-float inv2NW = 1.0 / (2.0 * float (TextureWidth));
-float inv2NH = 1.0 / (2.0 * float (TextureHeight));
-vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy);
-projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));
-projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_FBLIGHTMAP
+#define APPLY_RELIEFMAPPING
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+uniform float u_ShaderTime;
-myhalf3 refr = myhalf3(0.0);
-myhalf3 refl = myhalf3(0.0);
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
-#ifdef APPLY_EYEDOT
-// calculate dot product between the surface normal and eye vector
-// great for simulating varying water translucency based on the view angle
-myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5));
-vec3 eyeNormal = normalize(myhalf3(EyeVector));
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
-float refrdot = float(dot(surfaceNormal, eyeNormal));
-//refrdot = float (clamp (refrdot, 0.0, 1.0));
-float refldot = 1.0 - refrdot;
-// get refraction and reflection
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot;
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot;
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
-#ifdef APPLY_REFRACTION
-refr = (myhalf3(texture2D(RefractionTexture, projCoord)));
#endif
-#ifdef APPLY_REFLECTION
-refl = (myhalf3(texture2D(ReflectionTexture, projCoord)));
#endif
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
-// add reflection and refraction
-#ifdef APPLY_DISTORTION_ALPHA
-color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
#else
-color = myhalf3(gl_Color.rgb) + refr + refl;
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
#endif
-#ifdef APPLY_GRAYSCALE
-float grey = dot(color, myhalf3(0.299, 0.587, 0.114));
-gl_FragColor = vec4(vec3(grey),1.0);
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
#else
-gl_FragColor = vec4(vec3(color),1.0);
+ FogGen(Position, v_FogCoord);
#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
}
-#endif // FRAGMENT_SHADER
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/85.shader_test b/shaders/warsow/85.shader_test
index 9b644bc..d2d1c57 100644
--- a/shaders/warsow/85.shader_test
+++ b/shaders/warsow/85.shader_test
@@ -1,225 +1,2059 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec4 ProjVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-void main(void)
+if (numWeights > 2)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-mat4 textureMatrix;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-textureMatrix = gl_TextureMatrix[0];
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
-gl_Position = ftransform();
-ProjVector = textureMatrix * gl_Vertex;
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform myhalf3 LightAmbient;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
-uniform float TextureWidth, TextureHeight;
-uniform float ProjDistance;
-uniform sampler2DShadow ShadowmapTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
-void main(void)
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
{
-myhalf color = myhalf(1.0);
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
-if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance)
-discard;
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
-float dtW = 1.0 / TextureWidth;
-float dtH = 1.0 / TextureHeight;
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
-vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);
-coord = (coord + vec3 (1.0)) * vec3 (0.5);
-coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));
-coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));
-coord.r = float (clamp (float(coord.r), 0.0, 1.0));
+ myhalf3 weightedDiffuseNormalModelspace;
-myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r);
-myhalf shadow = shadow0;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
-#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
-vec3 coord2 = coord + vec3(0.0, dtH, 0.0);
-myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
-coord2 = coord + vec3(dtW, dtH, 0.0);
-myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT
-coord2 = coord + vec3(dtW, 0.0, 0.0);
-myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-#if defined(APPLY_PCF3x3)
-coord2 = coord + vec3(-dtW, 0.0, 0.0);
-myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(-dtW, -dtH, 0.0);
-myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(0.0, -dtH, 0.0);
-myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(dtW, -dtH, 0.0);
-myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-coord2 = coord + vec3(-dtW, dtH, 0.0);
-myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11);
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25);
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-shadow = shadow0;
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
-float attenuation = float (ProjVector.w) / ProjDistance;
-myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z))
-;compensation = max (compensation, 0.0);
-color = shadow + attenuation + compensation;
+#endif // APPLY_DECAL
-gl_FragColor = vec4(vec3(color),1.0);
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
#endif
-varying vec4 ProjVector;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
-mat4 textureMatrix;
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
-textureMatrix = gl_TextureMatrix[0];
+vec4 DQReal1, DQDual1;
+float scale;
-gl_Position = ftransform();
-ProjVector = textureMatrix * gl_Vertex;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
}
-#endif // VERTEX_SHADER
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform myhalf3 LightAmbient;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
-uniform float TextureWidth, TextureHeight;
-uniform float ProjDistance;
-uniform sampler2DShadow ShadowmapTexture;
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
-void main(void)
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
{
-myhalf color = myhalf(1.0);
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
-if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance)
-discard;
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
-float dtW = 1.0 / TextureWidth;
-float dtH = 1.0 / TextureHeight;
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
-vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);
-coord = (coord + vec3 (1.0)) * vec3 (0.5);
-coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));
-coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));
-coord.r = float (clamp (float(coord.r), 0.0, 1.0));
+ myhalf3 weightedDiffuseNormalModelspace;
-myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r);
-myhalf shadow = shadow0;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
-#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
-vec3 coord2 = coord + vec3(0.0, dtH, 0.0);
-myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
-coord2 = coord + vec3(dtW, dtH, 0.0);
-myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT
-coord2 = coord + vec3(dtW, 0.0, 0.0);
-myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
-#if defined(APPLY_PCF3x3)
-coord2 = coord + vec3(-dtW, 0.0, 0.0);
-myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(-dtW, -dtH, 0.0);
-myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(0.0, -dtH, 0.0);
-myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
-coord2 = coord + vec3(dtW, -dtH, 0.0);
-myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
-coord2 = coord + vec3(-dtW, dtH, 0.0);
-myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r);
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11);
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
#else
-shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25);
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
#else
-shadow = shadow0;
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
#endif
-float attenuation = float (ProjVector.w) / ProjDistance;
-myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z))
-;compensation = max (compensation, 0.0);
-color = shadow + attenuation + compensation;
+#endif // APPLY_DECAL
-gl_FragColor = vec4(vec3(color),1.0);
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/88.shader_test b/shaders/warsow/88.shader_test
index b4f6f7c..97d2c67 100644
--- a/shaders/warsow/88.shader_test
+++ b/shaders/warsow/88.shader_test
@@ -1,103 +1,2061 @@
[require]
GLSL >= 1.10
-[fragment shader]
-#define FRAGMENT_SHADER
-// Warsow GLSL shader
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 ProjVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
-uniform float OutlineHeight;
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-void main(void)
+if (numWeights > 2)
{
-gl_FrontColor = gl_Color;
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-vec4 n = vec4(gl_Normal.xyz, 0.0);
-vec4 v = vec4(gl_Vertex) + n * OutlineHeight;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
-gl_Position = gl_ModelViewProjectionMatrix * v;
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * v;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform float OutlineCutOff;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-void main(void)
+void main()
{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
-#ifdef APPLY_OUTLINES_CUTOFF
-if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff))
-discard;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-gl_FragColor = vec4 (gl_Color);
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
+[fragment shader]
+#version 130
-[vertex shader]
-#define VERTEX_SHADER
-// Warsow GLSL shader
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
-varying vec4 ProjVector;
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
-uniform float OutlineHeight;
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
-void main(void)
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
{
-gl_FrontColor = gl_Color;
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
-vec4 n = vec4(gl_Normal.xyz, 0.0);
-vec4 v = vec4(gl_Vertex) + n * OutlineHeight;
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
-gl_Position = gl_ModelViewProjectionMatrix * v;
-ProjVector = gl_Position;
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * v;
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
#endif
}
-#endif // VERTEX_SHADER
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_VERTEX
+#define APPLY_ALPHA_VERTEX
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_RELIEFMAPPING
+#define APPLY_DIRECTIONAL_LIGHT_MIX
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform float OutlineCutOff;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-void main(void)
+void main()
{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
-#ifdef APPLY_OUTLINES_CUTOFF
-if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff))
-discard;
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
#endif
-gl_FragColor = vec4 (gl_Color);
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
}
#endif // FRAGMENT_SHADER
-
diff --git a/shaders/warsow/91.shader_test b/shaders/warsow/91.shader_test
index e32eb19..97a04bf 100644
--- a/shaders/warsow/91.shader_test
+++ b/shaders/warsow/91.shader_test
@@ -2,56 +2,2062 @@
GLSL >= 1.10
[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
#define VERTEX_SHADER
-// Warsow GLSL shader
-
-#if !defined(__GLSL_CG_DATA_TYPES)
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
#define myhalf float
#define myhalf2 vec2
#define myhalf3 vec3
#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
#else
-#define myhalf half
-#define myhalf2 half2
-#define myhalf3 half3
-#define myhalf4 half4
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
-varying vec2 TexCoord;
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
#ifdef VERTEX_SHADER
-// Vertex shader
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
-uniform float TurbAmplitude, TurbPhase;
+uniform vec4 u_TextureParams;
-void main(void)
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
{
-gl_FrontColor = gl_Color;
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
-vec4 turb;
-turb = vec4(gl_MultiTexCoord0);
-turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI );
-turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI );
-TexCoord = vec2(gl_TextureMatrix[0] * turb);
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
-gl_Position = ftransform();
-#ifdef APPLY_CLIPPING
-#ifdef __GLSL_CG_DATA_TYPES
-gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
}
#endif // VERTEX_SHADER
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define NUM_BONE_INFLUENCES 4
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_HALFLAMBERT
+#define APPLY_ENTITY_DECAL
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
// Fragment shader
-uniform sampler2D BaseTexture;
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
-void main(void)
+void main()
{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
diff --git a/shaders/warsow/94.shader_test b/shaders/warsow/94.shader_test
new file mode 100644
index 0000000..4cd298b
--- /dev/null
+++ b/shaders/warsow/94.shader_test
@@ -0,0 +1,2059 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_HALFLAMBERT
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define APPLY_DIRECTIONAL_LIGHT
+#define APPLY_SPECULAR
+#define APPLY_HALFLAMBERT
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
diff --git a/shaders/warsow/97.shader_test b/shaders/warsow/97.shader_test
new file mode 100644
index 0000000..6dddd6d
--- /dev/null
+++ b/shaders/warsow/97.shader_test
@@ -0,0 +1,2057 @@
+[require]
+GLSL >= 1.10
+
+[vertex shader]
+#version 130
+#extension GL_ARB_draw_instanced : enable
+#define QF_GLSL_VERSION 130
+#define VERTEX_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+
+[fragment shader]
+#version 130
+
+#define QF_GLSL_VERSION 130
+#define FRAGMENT_SHADER
+#if !defined(myhalf)
+//#if !defined(__GLSL_CG_DATA_TYPES)
+#define myhalf float
+#define myhalf2 vec2
+#define myhalf3 vec3
+#define myhalf4 vec4
+//#else
+//#define myhalf half
+//#define myhalf2 half2
+//#define myhalf3 half3
+//#define myhalf4 half4
+//#endif
+#endif
+
+#if QF_GLSL_VERSION >= 130
+ precision highp float;
+
+# ifdef VERTEX_SHADER
+ out myhalf4 qf_FrontColor;
+# define qf_varying out
+# define qf_attribute in
+# endif
+# ifdef FRAGMENT_SHADER
+ in myhalf4 qf_FrontColor;
+ out myhalf4 qf_FragColor;
+# define qf_varying in
+# define qf_attribute in
+# endif
+
+# define qf_texture texture
+# define qf_textureCube texture
+# define qf_textureLod textureLod
+# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))
+# define qf_shadow texture
+#else
+# ifdef VERTEX_SHADER
+# define qf_FrontColor gl_FrontColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+
+# ifdef FRAGMENT_SHADER
+# define qf_FrontColor gl_Color
+# define qf_FragColor gl_FragColor
+# define qf_varying varying
+# define qf_attribute attribute
+# endif
+# define qf_texture texture2D
+# define qf_textureLod texture2DLod
+# define qf_textureCube textureCube
+# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))
+# define qf_shadow shadow2D
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef MAX_UNIFORM_BONES
+#define MAX_UNIFORM_BONES 100
+#endif
+
+#ifndef MAX_UNIFORM_INSTANCES
+#define MAX_UNIFORM_INSTANCES 40
+#endif
+uniform vec3 u_QF_ViewOrigin;
+uniform mat3 u_QF_ViewAxis;
+uniform float u_QF_MirrorSide;
+uniform vec3 u_QF_EntityOrigin;
+uniform float u_QF_ShaderTime;
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_TWOPI
+#define M_TWOPI 6.28318530717958647692
+#endif
+
+#ifndef WAVE_SIN
+float QF_WaveFunc_Sin(float x)
+{
+x -= floor(x);
+return sin(x * M_TWOPI);
+}
+float QF_WaveFunc_Triangle(float x)
+{
+x -= floor(x);
+return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0);
+}
+float QF_WaveFunc_Square(float x)
+{
+x -= floor(x);
+return step(x, 0.5) * 2.0 - 1.0;
+}
+float QF_WaveFunc_Sawtooth(float x)
+{
+x -= floor(x);
+return x;
+}
+float QF_QF_WaveFunc_InverseSawtooth(float x)
+{
+x -= floor(x);
+return 1.0 - x;
+}
+
+#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq))))
+#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq))))
+#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq))))
+#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq))))
+#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq))))
+#endif
+
+#ifdef VERTEX_SHADER
+attribute vec4 a_BonesIndices;
+attribute vec4 a_BonesWeights;
+
+uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2];
+
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+// use defines to overload the transform function
+
+#define DUAL_QUAT_TRANSFORM_NORMALS
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#define DUAL_QUAT_TRANSFORM_TANGENT
+#if defined(DUAL_QUAT_TRANSFORM_NORMALS)
+#if defined(DUAL_QUAT_TRANSFORM_TANGENT)
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent)
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal)
+#endif
+#else
+void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position)
+#endif
+{
+int index;
+vec4 Indices = a_BonesIndices;
+vec4 Weights = a_BonesWeights;
+vec4 Indices_2 = Indices * 2.0;
+vec4 DQReal, DQDual;
+
+index = int(Indices_2.x);
+DQReal = u_QF_DualQuats[index+0];
+DQDual = u_QF_DualQuats[index+1];
+
+if (numWeights > 1)
+{
+DQReal *= Weights.x;
+DQDual *= Weights.x;
+
+vec4 DQReal1, DQDual1;
+float scale;
+
+index = int(Indices_2.y);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 2)
+{
+index = int(Indices_2.z);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+
+if (numWeights > 3)
+{
+index = int(Indices_2.w);
+DQReal1 = u_QF_DualQuats[index+0];
+DQDual1 = u_QF_DualQuats[index+1];
+// antipodality handling
+scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w;
+DQReal += DQReal1 * scale;
+DQDual += DQDual1 * scale;
+}
+}
+}
+
+float len = length(DQReal);
+DQReal /= len;
+DQDual /= len;
+
+Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz;
+
+#ifdef DUAL_QUAT_TRANSFORM_NORMALS
+Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal;
+#endif
+
+#ifdef DUAL_QUAT_TRANSFORM_TANGENT
+Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent;
+#endif
+}
+
+#endif
+#ifdef VERTEX_SHADER
+#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS
+attribute vec4 a_InstanceQuat;
+attribute vec4 a_InstancePosAndScale;
+#elif defined(GL_ARB_draw_instanced)
+
+uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2];
+
+#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2]
+#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1]
+#else
+uniform vec4 u_QF_InstancePoints[2];
+#define a_InstanceQuat u_QF_InstancePoints[0]
+#define a_InstancePosAndScale u_QF_InstancePoints[1]
+#endif
+
+void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal)
+{
+Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) *
+ a_InstancePosAndScale.w + a_InstancePosAndScale.xyz;
+Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal;
+}
+
+#endif
+#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x))
+
+#define APPLY_RGB_CONST
+#define APPLY_ALPHA_CONST
+#define NUM_LIGHTMAPS 1
+#define APPLY_SPECULAR
+
+#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z)
+uniform mat4 u_ModelViewMatrix;
+uniform mat4 u_ModelViewProjectionMatrix;
+
+uniform float u_ShaderTime;
+
+uniform vec3 u_ViewOrigin;
+uniform mat3 u_ViewAxis;
+
+uniform vec3 u_EntityDist;
+uniform vec3 u_EntityOrigin;
+uniform myhalf4 u_EntityColor;
+
+uniform myhalf4 u_ConstColor;
+uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs;
+uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors
+
+uniform myhalf3 u_LightAmbient;
+uniform myhalf3 u_LightDiffuse;
+uniform vec3 u_LightDir;
+
+uniform myhalf2 u_BlendMix;
+
+uniform vec2 u_TextureMatrix[3];
+#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1])
+
+uniform float u_MirrorSide;
+
+uniform float u_ZNear, u_ZFar;
+
+uniform ivec4 u_Viewport; // x, y, width, height
+
+uniform vec4 u_TextureParams;
+
+uniform myhalf u_SoftParticlesScale;
+
+
+#if defined(NUM_DLIGHTS)
+#if defined(FRAGMENT_SHADER)
+#if defined(NUM_DLIGHTS)
+
+struct DynamicLight
+{
+ myhalf Radius;
+ vec3 Position;
+ myhalf3 Diffuse;
+};
+
+uniform DynamicLight u_DynamicLights[NUM_DLIGHTS];
+uniform int u_NumDynamicLights;
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#define DLIGHTS_SURFACE_NORMAL_IN
+#ifdef DLIGHTS_SURFACE_NORMAL_IN
+myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace)
+#else
+myhalf3 DynamicLightsSummaryColor(in vec3 Position)
+#endif
+{
+ myhalf3 Color = myhalf3(0.0);
+
+#if QF_GLSL_VERSION >= 330
+ for (int i = 0; i < u_NumDynamicLights; i++)
+#else
+ for (int i = 0; i < NUM_DLIGHTS; i++)
+#endif
+ {
+ myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position);
+ myhalf distance = length(STR);
+ myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0);
+
+ falloff *= falloff;
+
+ #ifdef DLIGHTS_SURFACE_NORMAL_IN
+ falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0));
+ #endif
+
+ Color += falloff * u_DynamicLights[i].Diffuse;
+ }
+
+ return Color;
+}
+
+
+#endif
+
+#endif
+#endif
+
+#ifdef APPLY_FOG
+struct Fog
+{
+ float EyeDist;
+ vec4 EyePlane, Plane;
+ myhalf3 Color;
+ float Scale;
+};
+
+uniform Fog u_Fog;
+
+#define FOG_TEXCOORD_STEP 1.0/256.0
+
+#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1])
+
+#define FOG_GEN_OUTPUT_COLOR
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+
+#undef FOG_GEN_OUTPUT_COLOR
+#define FOG_GEN_OUTPUT_TEXCOORDS
+#if defined(FOG_GEN_OUTPUT_COLOR)
+void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix)
+#elif defined(FOG_GEN_OUTPUT_TEXCOORDS)
+void FogGen(in vec4 Position, inout vec2 outTexCoord)
+#endif
+{
+ // side = vec2(inside, outside)
+ myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist));
+ myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w;
+ myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w;
+ myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist);
+
+#if defined(FOG_GEN_OUTPUT_COLOR)
+ myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale));
+ myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0));
+ outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy);
+#endif
+
+#if defined(FOG_GEN_OUTPUT_TEXCOORDS)
+ myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale));
+ myhalf FogT = -FVdist;
+ outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP);
+#endif
+}
+
+#endif
+#ifdef APPLY_GREYSCALE
+myhalf3 Greyscale(myhalf3 color)
+{
+ return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114)));
+}
+
+#endif
+
+qf_varying vec2 v_TexCoord;
+#ifdef NUM_LIGHTMAPS
+qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS];
+#endif
+
+qf_varying vec3 v_Position;
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+qf_varying vec3 v_EyeVector;
+#endif
+
+qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+qf_varying vec2 v_FogCoord;
+#endif
+
+#ifdef VERTEX_SHADER
+#ifdef VERTEX_SHADER
+qf_attribute vec4 a_Position;
+qf_attribute vec4 a_SVector;
+qf_attribute vec4 a_Normal;
+qf_attribute vec4 a_Color;
+qf_attribute vec2 a_TexCoord;
+qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3;
+#endif
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+
+void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord)
+{
+#ifdef NUM_BONE_INFLUENCES
+ QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent);
+#endif
+
+#ifdef APPLY_DEFORMVERTS
+ QF_DeformVerts(Position, Normal, TexCoord);
+#endif
+
+#ifdef APPLY_INSTANCED_TRANSFORMS
+ QF_InstancedTransform(Position, Normal);
+#endif
+}
+myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor)
+{
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1)
+#endif
+
+#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST)
+ myhalf4 Color = u_ConstColor;
+#else
+ myhalf4 Color = myhalf4(1.0);
+
+#if defined(APPLY_RGB_CONST)
+ Color.rgb = u_ConstColor.rgb;
+#elif defined(APPLY_RGB_VERTEX)
+ Color.rgb = VertexColor.rgb;
+#elif defined(APPLY_RGB_ONE_MINUS_VERTEX)
+ Color.rgb = myhalf3(1.0) - VertexColor.rgb;
+#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT)
+ Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse);
+#endif
+
+#if defined(APPLY_ALPHA_CONST)
+ Color.a = u_ConstColor.a;
+#elif defined(APPLY_ALPHA_VERTEX)
+ Color.a = VertexColor.a;
+#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX)
+ Color.a = 1.0 - VertexColor.a;
+#endif
+
+#endif
+
+#ifdef APPLY_RGB_DISTANCERAMP
+ Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]);
+#endif
+
+#ifdef APPLY_ALPHA_DISTANCERAMP
+ Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]);
+#endif
+
+ return Color;
+#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP)
+#undef DISTANCERAMP
+#endif
+}
+
+
+void main()
+{
+ vec4 Position = a_Position;
+ vec3 Normal = a_Normal.xyz;
+ myhalf4 inColor = myhalf4(a_Color);
+ vec2 TexCoord = a_TexCoord;
+ vec3 Tangent = a_SVector.xyz;
+ float TangentDir = a_SVector.w;
+
+ TransformVerts(Position, Normal, Tangent, TexCoord);
+
+ myhalf4 outColor = VertexRGBGen(Position, Normal, inColor);
+
+#ifdef APPLY_FOG
+#if defined(APPLY_FOG_COLOR)
+ FogGen(Position, outColor, u_BlendMix);
+#else
+ FogGen(Position, v_FogCoord);
+#endif
+#endif // APPLY_FOG
+
+ qf_FrontColor = vec4(outColor);
+
+ v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord);
+
+#ifdef NUM_LIGHTMAPS
+ v_LightmapTexCoord[0] = a_LightmapCoord0;
+#if NUM_LIGHTMAPS >= 2
+ v_LightmapTexCoord[1] = a_LightmapCoord1;
+#if NUM_LIGHTMAPS >= 3
+ v_LightmapTexCoord[2] = a_LightmapCoord2;
+#if NUM_LIGHTMAPS >= 4
+ v_LightmapTexCoord[3] = a_LightmapCoord3;
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+ v_StrMatrix[0] = Tangent;
+ v_StrMatrix[2] = Normal;
+ v_StrMatrix[1] = TangentDir * cross(Normal, Tangent);
+
+#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz;
+ v_EyeVector = EyeVectorWorld * v_StrMatrix;
+#endif
+
+ v_Position = Position.xyz;
+ gl_Position = u_ModelViewProjectionMatrix * Position;
+}
+
+#endif // VERTEX_SHADER
+
+#ifdef FRAGMENT_SHADER
+// Fragment shader
+
+#ifdef NUM_LIGHTMAPS
+uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord
+uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS];
+#endif
+
+uniform sampler2D u_BaseTexture;
+uniform sampler2D u_NormalmapTexture;
+uniform sampler2D u_GlossTexture;
+#ifdef APPLY_DECAL
+uniform sampler2D u_DecalTexture;
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+uniform sampler2D u_EntityDecalTexture;
+#endif
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+uniform float u_OffsetMappingScale;
+#endif
+
+#ifdef APPLY_DRAWFLAT
+uniform myhalf3 u_WallColor;
+uniform myhalf3 u_FloorColor;
+#endif
+
+uniform myhalf u_GlossIntensity; // gloss scaling factor
+uniform myhalf u_GlossExponent; // gloss exponent factor
+
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+// The following reliefmapping and offsetmapping routine was taken from DarkPlaces
+// The credit goes to LordHavoc (as always)
+vec2 OffsetMapping(vec2 TexCoord)
+{
+#ifdef APPLY_RELIEFMAPPING
+ // 14 sample relief mapping: linear search and then binary search
+ // this basically steps forward a small amount repeatedly until it finds
+ // itself inside solid, then jitters forward and back using decreasing
+ // amounts to find the impact
+ //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1);
+ //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1);
+ vec3 RT = vec3(TexCoord, 1);
+ OffsetVector *= 0.1;
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);
+ RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);
+ return RT.xy;
+#else
+ // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)
+ // this basically moves forward the full distance, and then backs up based
+ // on height of samples
+ //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1));
+ //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1));
+ vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1));
+ TexCoord += OffsetVector;
+ OffsetVector *= 0.5;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a;
+ return TexCoord;
+#endif // APPLY_RELIEFMAPPING
+}
+#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+
+void main()
+{
+#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)
+ // apply offsetmapping
+ vec2 TexCoordOffset = OffsetMapping(v_TexCoord);
+#define v_TexCoord TexCoordOffset
+#endif
+
+ myhalf3 surfaceNormal;
+ myhalf3 surfaceNormalModelspace;
+ myhalf3 diffuseNormalModelspace;
+ float diffuseProduct;
+
+#ifdef APPLY_CELSHADING
+ int lightcell;
+ float diffuseProductPositive;
+ float diffuseProductNegative;
+ float hardShadow;
+#endif
+
+ myhalf3 weightedDiffuseNormalModelspace;
+
+#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS)
+ myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);
+#else
+ myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);
+#endif
+
+ myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0);
+
+ // get the surface normal
+ surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5));
+ surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal);
+
+#ifdef APPLY_DIRECTIONAL_LIGHT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+ diffuseNormalModelspace = v_StrMatrix[2];
+#else
+ diffuseNormalModelspace = u_LightDir;
+#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL
+
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+
+#ifdef APPLY_CELSHADING
+ hardShadow = 0.0;
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProductPositive *= diffuseProductPositive;
+ diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 );
+ diffuseProductNegative *= diffuseProductNegative;
+ diffuseProductNegative -= 0.25;
+ diffuseProduct = diffuseProductPositive;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ diffuseProductPositive = max (diffuseProduct, 0.0);
+ diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3);
+#endif // APPLY_HALFLAMBERT
+
+ // smooth the hard shadow edge
+ lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0);
+ hardShadow += float(lightcell);
+
+ lightcell = int(diffuseProductPositive * 2.0);
+ hardShadow += float(lightcell);
+
+ color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14);
+
+ // backlight
+ lightcell = int (diffuseProductNegative * 2.0);
+ color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085);
+#else
+
+#ifdef APPLY_HALFLAMBERT
+ diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 );
+ diffuseProduct *= diffuseProduct;
+#else
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+#endif // APPLY_HALFLAMBERT
+
+#ifdef APPLY_DIRECTIONAL_LIGHT_MIX
+ color.rgb += qf_FrontColor.rgb;
+#else
+ color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient;
+#endif
+
+#endif // APPLY_CELSHADING
+
+#endif // APPLY_DIRECTIONAL_LIGHT
+
+ // deluxemapping using light vectors in modelspace
+
+#ifdef NUM_LIGHTMAPS
+ // get light normal
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5));
+ // calculate directional shading
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+
+#ifdef APPLY_FBLIGHTMAP
+ weightedDiffuseNormalModelspace = diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0])));
+#else
+#define NORMALIZE_DIFFUSE_NORMAL
+ weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace;
+ // apply lightmap color
+ color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0]));
+#endif // APPLY_FBLIGHTMAP
+
+#ifdef APPLY_AMBIENT_COMPENSATION
+ // compensate for ambient lighting
+ color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient;
+#endif
+
+#if NUM_LIGHTMAPS >= 2
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1]));
+#if NUM_LIGHTMAPS >= 3
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2]));
+#if NUM_LIGHTMAPS >= 4
+ diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5));
+ diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace));
+ weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace;
+ color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3]));
+#endif // NUM_LIGHTMAPS >= 4
+#endif // NUM_LIGHTMAPS >= 3
+#endif // NUM_LIGHTMAPS >= 2
+#endif // NUM_LIGHTMAPS
+
+#if defined(NUM_DLIGHTS)
+ color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace);
+#endif
+
+#ifdef APPLY_SPECULAR
+
+#ifdef NORMALIZE_DIFFUSE_NORMAL
+ myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position)));
+#else
+ myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position)));
+#endif
+
+ myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal));
+ color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent);
+#endif // APPLY_SPECULAR
+
+#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+ color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ myhalf4 diffuse;
+
+#ifdef APPLY_DRAWFLAT
+ myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z)));
+ diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a));
+#else
+ diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord));
+#endif
+
+#ifdef APPLY_ENTITY_DECAL
+
+#ifdef APPLY_ENTITY_DECAL_ADD
+ decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb += u_EntityColor.rgb * decal.rgb;
+#else
+ decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord));
+ diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a);
+#endif // APPLY_ENTITY_DECAL_ADD
+
+#endif // APPLY_ENTITY_DECAL
+
+color = color * diffuse;
+#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT)
+
+#ifdef APPLY_DECAL
+
+#ifdef APPLY_DECAL_ADD
+ decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = decal.rgb + color.rgb;
+ color.a = color.a * myhalf(qf_FrontColor.a);
+#else
+ decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord));
+ color.rgb = mix(color.rgb, decal.rgb, decal.a);
+#endif // APPLY_DECAL_ADD
+
+#else
+
+#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX)
+ color = color;
+#else
+ color = color * myhalf4(qf_FrontColor);
+#endif
+
+#endif // APPLY_DECAL
+
+#ifdef APPLY_GREYSCALE
+ color.rgb = Greyscale(color.rgb);
+#endif
+
+#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR)
+ myhalf fogDensity = FogDensity(v_FogCoord);
+ color.rgb = mix(color.rgb, u_Fog.Color, fogDensity);
+#endif
+
+ qf_FragColor = vec4(color);
+}
+
+#endif // FRAGMENT_SHADER
+